mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-28 00:06:09 +03:00
1476 lines
60 KiB
C
1476 lines
60 KiB
C
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||
|
// 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 <memory>
|
||
|
#include <string>
|
||
|
#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/checked_range.h"
|
||
|
#include "base/containers/cxx20_erase_vector.h"
|
||
|
#include "base/containers/flat_map.h"
|
||
|
#include "base/containers/span.h"
|
||
|
#include "base/strings/string_piece.h"
|
||
|
#include "base/trace_event/base_tracing_forward.h"
|
||
|
#include "base/value_iterators.h"
|
||
|
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||
|
#include "third_party/abseil-cpp/absl/types/variant.h"
|
||
|
|
||
|
namespace base {
|
||
|
|
||
|
class DictionaryValue;
|
||
|
class ListValue;
|
||
|
|
||
|
// 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>`), `base::StringPiece`, `base::StringPiece16`,
|
||
|
// `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 `absl::nullopt`/`nullptr` if
|
||
|
// the `Value` does not have the correct subtype; otherwise, returns the value
|
||
|
// wrapped in an `absl::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 `StringPiece` 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 `absl::nullopt` or
|
||
|
// `nullptr` if the key is not present or the value has the wrong subtype.
|
||
|
// - `Set()`: Associate a value with a `StringPiece` 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 `absl::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()`,
|
||
|
// `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.
|
||
|
//
|
||
|
// ## Refactoring Notes
|
||
|
//
|
||
|
// `Value` was originally implemented as a class hierarchy, with a `Value` base
|
||
|
// class, and a leaf class for each of the different types of `Value` subtypes.
|
||
|
// https://docs.google.com/document/d/1uDLu5uTRlCWePxQUEHc8yNQdEoE1BDISYdpggWEABnw
|
||
|
// proposed an overhaul of the `Value` API that has now largely been
|
||
|
// implemented, though there remains a significant amount of legacy code that is
|
||
|
// still being migrated as part of the code health migration.
|
||
|
//
|
||
|
// OLD WAY:
|
||
|
//
|
||
|
// std::unique_ptr<base::Value> GetFoo() {
|
||
|
// std::unique_ptr<DictionaryValue> dict;
|
||
|
// dict->SetString("mykey", "foo");
|
||
|
// return dict;
|
||
|
// }
|
||
|
//
|
||
|
// NEW WAY:
|
||
|
//
|
||
|
// base::Value GetFoo() {
|
||
|
// base::Value::Dict dict;
|
||
|
// dict.SetString("mykey", "abc");
|
||
|
// return base::Value(std::move(dict));
|
||
|
// }
|
||
|
//
|
||
|
// To avoid losing type information with the new variant-based design, migration
|
||
|
// off the deprecated types should use more specific subtypes where possible:
|
||
|
//
|
||
|
// OLD WAY:
|
||
|
//
|
||
|
// void AlwaysTakesList(std::unique_ptr<base::ListValue> list);
|
||
|
// void AlwaysTakesDict(std::unique_ptr<base::DictionaryValue> dict);
|
||
|
//
|
||
|
// DEPRECATED (PREVIOUS) WAY:
|
||
|
//
|
||
|
// void AlwaysTakesList(std::vector<base::Value> list);
|
||
|
// void AlwaysTakesListAlternative1(base::Value::ConstListView list);
|
||
|
// void AlwaysTakesListAlternative2(base::Value::ListView& list);
|
||
|
// void AlwaysTakesListAlterantive3(base::Value::ListStorage);
|
||
|
// void AlwaysTakesDict(base::flat_map<std::string, base::Value> dict);
|
||
|
// void AlwaysTakesDictAlternative(base::Value::DictStorage);
|
||
|
//
|
||
|
// NEW WAY:
|
||
|
//
|
||
|
// void AlwaysTakesList(base::Value::List list);
|
||
|
// void AlwaysTakesDict(base::Value::Dict dict);
|
||
|
//
|
||
|
// Migrating code may require conversions on API boundaries. If something seems
|
||
|
// awkward/inefficient, please reach out to #code-health-rotation on Slack for
|
||
|
// consultation: it is entirely possible that certain classes of APIs may be
|
||
|
// missing due to an unrealized need.
|
||
|
class BASE_EXPORT GSL_OWNER Value {
|
||
|
public:
|
||
|
using BlobStorage = std::vector<uint8_t>;
|
||
|
|
||
|
using DeprecatedListStorage = std::vector<Value>;
|
||
|
using DeprecatedDictStorage = flat_map<std::string, Value>;
|
||
|
// TODO(https://crbug.com/1291666): Make these private.
|
||
|
using ListStorage = DeprecatedListStorage;
|
||
|
using DictStorage = DeprecatedDictStorage;
|
||
|
|
||
|
// Like `DictStorage`, but with std::unique_ptr in the mapped type. This is
|
||
|
// due to legacy reasons, and should be removed once no caller relies on
|
||
|
// stability of pointers anymore.
|
||
|
using LegacyDictStorage = flat_map<std::string, std::unique_ptr<Value>>;
|
||
|
|
||
|
using DeprecatedListView = CheckedContiguousRange<ListStorage>;
|
||
|
using DeprecatedConstListView = CheckedContiguousConstRange<ListStorage>;
|
||
|
// TODO(https://crbug.com/1291666): Make these private.
|
||
|
using ListView = DeprecatedListView;
|
||
|
using ConstListView = DeprecatedConstListView;
|
||
|
|
||
|
class Dict;
|
||
|
class List;
|
||
|
|
||
|
enum class Type : unsigned char {
|
||
|
NONE = 0,
|
||
|
BOOLEAN,
|
||
|
INTEGER,
|
||
|
DOUBLE,
|
||
|
STRING,
|
||
|
BINARY,
|
||
|
DICT,
|
||
|
// TODO(https://crbug.com/1291670): Deprecated and will be removed.
|
||
|
DICTIONARY = DICT,
|
||
|
LIST,
|
||
|
// Note: Do not add more types. See the file-level comment above for why.
|
||
|
};
|
||
|
|
||
|
// Adaptors for converting from the old way to the new way and vice versa.
|
||
|
static Value FromUniquePtrValue(std::unique_ptr<Value> val);
|
||
|
static std::unique_ptr<Value> ToUniquePtrValue(Value val);
|
||
|
static const DictionaryValue& AsDictionaryValue(const Value& val);
|
||
|
static const ListValue& AsListValue(const Value& val);
|
||
|
|
||
|
Value() noexcept;
|
||
|
|
||
|
Value(Value&&) noexcept;
|
||
|
Value& operator=(Value&&) noexcept;
|
||
|
|
||
|
// Deleted to prevent accidental copying.
|
||
|
Value(const Value&) = delete;
|
||
|
Value& operator=(const Value&) = delete;
|
||
|
|
||
|
// Creates a deep copy of this value.
|
||
|
Value Clone() const;
|
||
|
|
||
|
// Creates a `Value` of `type`. The data of the corresponding type will be
|
||
|
// default constructed.
|
||
|
explicit Value(Type type);
|
||
|
|
||
|
// Constructor for `Value::Type::BOOLEAN`.
|
||
|
explicit Value(bool value);
|
||
|
|
||
|
// Prevent pointers from implicitly converting to bool. Another way to write
|
||
|
// this would be to template the bool constructor and use SFINAE to only allow
|
||
|
// use if `std::is_same_v<T, bool>` is true, but this has surprising behavior
|
||
|
// with range-based for loops over a `std::vector<bool>` (which will
|
||
|
// unintuitively match the int overload instead).
|
||
|
//
|
||
|
// The `const` is load-bearing; otherwise, a `char*` argument would prefer the
|
||
|
// deleted overload due to requiring a qualification conversion.
|
||
|
template <typename T>
|
||
|
explicit Value(const T*) = delete;
|
||
|
|
||
|
// Constructor for `Value::Type::INT`.
|
||
|
explicit Value(int value);
|
||
|
|
||
|
// Constructor for `Value::Type::DOUBLE`.
|
||
|
explicit Value(double value);
|
||
|
|
||
|
// Constructors for `Value::Type::STRING`.
|
||
|
explicit Value(StringPiece value);
|
||
|
explicit Value(StringPiece16 value);
|
||
|
// `char*` and `char16_t*` are needed to provide a more specific overload than
|
||
|
// the deleted `const T*` overload above.
|
||
|
explicit Value(const char* value);
|
||
|
explicit Value(const char16_t* value);
|
||
|
// `std::string&&` allows for efficient move construction.
|
||
|
explicit Value(std::string&& value) noexcept;
|
||
|
|
||
|
// Constructors for `Value::Type::BINARY`.
|
||
|
explicit Value(const std::vector<char>& value);
|
||
|
explicit Value(base::span<const uint8_t> value);
|
||
|
explicit Value(BlobStorage&& value) noexcept;
|
||
|
|
||
|
// Constructor for `Value::Type::DICT`.
|
||
|
explicit Value(Dict&& value) noexcept;
|
||
|
|
||
|
// Constructor for `Value::Type::LIST`.
|
||
|
explicit Value(List&& value) noexcept;
|
||
|
|
||
|
// DEPRECATED: prefer `Value(Dict&&)`.
|
||
|
explicit Value(const DictStorage& value);
|
||
|
explicit Value(DictStorage&& value);
|
||
|
|
||
|
// DEPRECATED: prefer `Value(List&&)`.
|
||
|
explicit Value(span<const Value> value);
|
||
|
explicit Value(ListStorage&& value) noexcept;
|
||
|
|
||
|
~Value();
|
||
|
|
||
|
// Returns the name for a given `type`.
|
||
|
static const char* GetTypeName(Type type);
|
||
|
|
||
|
// Returns the type of the value stored by the current Value object.
|
||
|
Type type() const { return static_cast<Type>(data_.index()); }
|
||
|
|
||
|
// Returns true if the current object represents a given type.
|
||
|
bool is_none() const { return type() == Type::NONE; }
|
||
|
bool is_bool() const { return type() == Type::BOOLEAN; }
|
||
|
bool is_int() const { return type() == Type::INTEGER; }
|
||
|
bool is_double() const { return type() == Type::DOUBLE; }
|
||
|
bool is_string() const { return type() == Type::STRING; }
|
||
|
bool is_blob() const { return type() == Type::BINARY; }
|
||
|
bool is_dict() const { return type() == Type::DICT; }
|
||
|
bool is_list() const { return type() == Type::LIST; }
|
||
|
|
||
|
// Returns the stored data if the type matches, or `absl::nullopt`/`nullptr`
|
||
|
// otherwise. `bool`, `int`, and `double` are returned in a wrapped
|
||
|
// `absl::optional`; blobs, `Value::Dict`, and `Value::List` are returned by
|
||
|
// pointer.
|
||
|
absl::optional<bool> GetIfBool() const;
|
||
|
absl::optional<int> GetIfInt() const;
|
||
|
// Returns a non-null value for both `Value::Type::DOUBLE` and
|
||
|
// `Value::Type::INT`, converting the latter to a double.
|
||
|
absl::optional<double> GetIfDouble() const;
|
||
|
const std::string* GetIfString() const;
|
||
|
std::string* GetIfString();
|
||
|
const BlobStorage* GetIfBlob() const;
|
||
|
const Dict* GetIfDict() const;
|
||
|
Dict* GetIfDict();
|
||
|
const List* GetIfList() const;
|
||
|
List* GetIfList();
|
||
|
|
||
|
// Similar to the `GetIf...()` variants above, but fails with a `CHECK()` on a
|
||
|
// type mismatch. `bool`, `int`, and `double` are returned by value; blobs,
|
||
|
// `Value::Dict`, and `Value::List` are returned by reference.
|
||
|
bool GetBool() const;
|
||
|
int GetInt() const;
|
||
|
// Returns a value for both `Value::Type::DOUBLE` and `Value::Type::INT`,
|
||
|
// converting the latter to a double.
|
||
|
double GetDouble() const;
|
||
|
const std::string& GetString() const;
|
||
|
std::string& GetString();
|
||
|
const BlobStorage& GetBlob() const;
|
||
|
const Dict& GetDict() const;
|
||
|
Dict& GetDict();
|
||
|
const List& GetList() const;
|
||
|
List& GetList();
|
||
|
|
||
|
// Represents a dictionary of string keys to Values.
|
||
|
class BASE_EXPORT GSL_OWNER Dict {
|
||
|
public:
|
||
|
using iterator = detail::dict_iterator;
|
||
|
using const_iterator = detail::const_dict_iterator;
|
||
|
|
||
|
Dict();
|
||
|
|
||
|
Dict(Dict&&) noexcept;
|
||
|
Dict& operator=(Dict&&) noexcept;
|
||
|
|
||
|
// Deleted to prevent accidental copying.
|
||
|
Dict(const Dict&) = delete;
|
||
|
Dict& operator=(const Dict&) = delete;
|
||
|
|
||
|
~Dict();
|
||
|
|
||
|
// TODO(dcheng): Probably need to allow construction from a pair of
|
||
|
// iterators for now due to the prevalence of DictStorage.
|
||
|
|
||
|
// Returns true if there are no entries in this dictionary and false
|
||
|
// otherwise.
|
||
|
bool empty() const;
|
||
|
|
||
|
// Returns the number of entries in this dictionary.
|
||
|
size_t size() const;
|
||
|
|
||
|
// Returns an iterator to the first entry in this dictionary.
|
||
|
iterator begin();
|
||
|
const_iterator begin() const;
|
||
|
const_iterator cbegin() const;
|
||
|
|
||
|
// Returns an iterator following the last entry in this dictionary. May not
|
||
|
// be dereferenced.
|
||
|
iterator end();
|
||
|
const_iterator end() const;
|
||
|
const_iterator cend() const;
|
||
|
|
||
|
// Returns true if `key` is an entry in this dictionary.
|
||
|
bool contains(base::StringPiece key) const;
|
||
|
|
||
|
// Removes all entries from this dictionary.
|
||
|
void clear();
|
||
|
|
||
|
// Removes the entry referenced by `pos` in this dictionary and returns an
|
||
|
// iterator to the entry following the removed entry.
|
||
|
iterator erase(iterator pos);
|
||
|
iterator erase(const_iterator pos);
|
||
|
|
||
|
// Creates a deep copy of this dictionary.
|
||
|
Dict Clone() const;
|
||
|
|
||
|
// Merges the entries from `dict` into this dictionary. If an entry with the
|
||
|
// same key exists in this dictionary and `dict`:
|
||
|
// - if both entries are dictionaries, they will be recursively merged
|
||
|
// - otherwise, the already-existing entry in this dictionary will be
|
||
|
// overwritten with the entry from `dict`.
|
||
|
void Merge(const Dict& dict);
|
||
|
|
||
|
// Finds the entry corresponding to `key` in this dictionary. Returns
|
||
|
// nullptr if there is no such entry.
|
||
|
const Value* Find(StringPiece key) const;
|
||
|
Value* Find(StringPiece key);
|
||
|
|
||
|
// Similar to `Find()` above, but returns `absl::nullopt`/`nullptr` if the
|
||
|
// type of the entry does not match. `bool`, `int`, and `double` are
|
||
|
// returned in a wrapped `absl::optional`; blobs, `Value::Dict`, and
|
||
|
// `Value::List` are returned by pointer.
|
||
|
absl::optional<bool> FindBool(StringPiece key) const;
|
||
|
absl::optional<int> FindInt(StringPiece key) const;
|
||
|
// Returns a non-null value for both `Value::Type::DOUBLE` and
|
||
|
// `Value::Type::INT`, converting the latter to a double.
|
||
|
absl::optional<double> FindDouble(StringPiece key) const;
|
||
|
const std::string* FindString(StringPiece key) const;
|
||
|
std::string* FindString(StringPiece key);
|
||
|
const BlobStorage* FindBlob(StringPiece key) const;
|
||
|
const Dict* FindDict(StringPiece key) const;
|
||
|
Dict* FindDict(StringPiece key);
|
||
|
const List* FindList(StringPiece key) const;
|
||
|
List* FindList(StringPiece key);
|
||
|
|
||
|
// Sets an entry with `key` and `value` in this dictionary, overwriting any
|
||
|
// existing entry with the same `key`. Returns a pointer to the set `value`.
|
||
|
Value* Set(StringPiece key, Value&& value);
|
||
|
Value* Set(StringPiece key, bool value);
|
||
|
template <typename T>
|
||
|
Value* Set(StringPiece, const T*) = delete;
|
||
|
Value* Set(StringPiece key, int value);
|
||
|
Value* Set(StringPiece key, double value);
|
||
|
Value* Set(StringPiece key, StringPiece value);
|
||
|
Value* Set(StringPiece key, StringPiece16 value);
|
||
|
Value* Set(StringPiece key, const char* value);
|
||
|
Value* Set(StringPiece key, const char16_t* value);
|
||
|
Value* Set(StringPiece key, std::string&& value);
|
||
|
Value* Set(StringPiece key, BlobStorage&& value);
|
||
|
Value* Set(StringPiece key, Dict&& value);
|
||
|
Value* Set(StringPiece key, List&& value);
|
||
|
|
||
|
// Removes the entry corresponding to `key` from this dictionary. Returns
|
||
|
// true if an entry was removed or false otherwise.
|
||
|
bool Remove(StringPiece key);
|
||
|
|
||
|
// Similar to `Remove()`, but returns the value corresponding to the removed
|
||
|
// entry or `absl::nullopt` otherwise.
|
||
|
absl::optional<Value> Extract(StringPiece key);
|
||
|
|
||
|
// Equivalent to the above methods but operating on paths instead of keys.
|
||
|
// A path is shorthand syntax for referring to a key nested inside
|
||
|
// intermediate dictionaries, with components delimited by ".". Paths may
|
||
|
// not be empty.
|
||
|
//
|
||
|
// Prefer the non-path methods above when possible. Paths that have only one
|
||
|
// component (i.e. no dots in the path) should never use the path-based
|
||
|
// methods.
|
||
|
//
|
||
|
// Originally, the path-based APIs were the only way of specifying a key, so
|
||
|
// there are likely to be many legacy (and unnecessary) uses of the path
|
||
|
// APIs that do not actually require traversing nested dictionaries.
|
||
|
const Value* FindByDottedPath(StringPiece path) const;
|
||
|
Value* FindByDottedPath(StringPiece path);
|
||
|
|
||
|
absl::optional<bool> FindBoolByDottedPath(StringPiece path) const;
|
||
|
absl::optional<int> FindIntByDottedPath(StringPiece path) const;
|
||
|
// Returns a non-null value for both `Value::Type::DOUBLE` and
|
||
|
// `Value::Type::INT`, converting the latter to a double.
|
||
|
absl::optional<double> FindDoubleByDottedPath(StringPiece path) const;
|
||
|
const std::string* FindStringByDottedPath(StringPiece path) const;
|
||
|
std::string* FindStringByDottedPath(StringPiece path);
|
||
|
const BlobStorage* FindBlobByDottedPath(StringPiece path) const;
|
||
|
const Dict* FindDictByDottedPath(StringPiece path) const;
|
||
|
Dict* FindDictByDottedPath(StringPiece path);
|
||
|
const List* FindListByDottedPath(StringPiece path) const;
|
||
|
List* FindListByDottedPath(StringPiece path);
|
||
|
|
||
|
// Creates a new entry with a dictionary for any non-last component that is
|
||
|
// missing an entry while performing the path traversal. Will fail if any
|
||
|
// non-last component of the path refers to an already-existing entry that
|
||
|
// is not a dictionary. Returns `nullptr` on failure.
|
||
|
Value* SetByDottedPath(StringPiece path, Value&& value);
|
||
|
Value* SetByDottedPath(StringPiece path, bool value);
|
||
|
template <typename T>
|
||
|
Value* SetByDottedPath(StringPiece, const T*) = delete;
|
||
|
Value* SetByDottedPath(StringPiece path, int value);
|
||
|
Value* SetByDottedPath(StringPiece path, double value);
|
||
|
Value* SetByDottedPath(StringPiece path, StringPiece value);
|
||
|
Value* SetByDottedPath(StringPiece path, StringPiece16 value);
|
||
|
Value* SetByDottedPath(StringPiece path, const char* value);
|
||
|
Value* SetByDottedPath(StringPiece path, const char16_t* value);
|
||
|
Value* SetByDottedPath(StringPiece path, std::string&& value);
|
||
|
Value* SetByDottedPath(StringPiece path, BlobStorage&& value);
|
||
|
Value* SetByDottedPath(StringPiece path, Dict&& value);
|
||
|
Value* SetByDottedPath(StringPiece path, List&& value);
|
||
|
|
||
|
bool RemoveByDottedPath(StringPiece path);
|
||
|
|
||
|
absl::optional<Value> ExtractByDottedPath(StringPiece path);
|
||
|
|
||
|
private:
|
||
|
BASE_EXPORT friend bool operator==(const Dict& lhs, const Dict& rhs);
|
||
|
BASE_EXPORT friend bool operator!=(const Dict& lhs, const Dict& rhs);
|
||
|
BASE_EXPORT friend bool operator<(const Dict& lhs, const Dict& rhs);
|
||
|
BASE_EXPORT friend bool operator>(const Dict& lhs, const Dict& rhs);
|
||
|
BASE_EXPORT friend bool operator<=(const Dict& lhs, const Dict& rhs);
|
||
|
BASE_EXPORT friend bool operator>=(const Dict& lhs, const Dict& rhs);
|
||
|
|
||
|
// For legacy access to the internal storage type.
|
||
|
friend Value;
|
||
|
|
||
|
explicit Dict(const flat_map<std::string, std::unique_ptr<Value>>& storage);
|
||
|
|
||
|
flat_map<std::string, std::unique_ptr<Value>> storage_;
|
||
|
};
|
||
|
|
||
|
// Represents a list of Values.
|
||
|
class BASE_EXPORT GSL_OWNER List {
|
||
|
public:
|
||
|
using iterator = CheckedContiguousIterator<Value>;
|
||
|
using const_iterator = CheckedContiguousConstIterator<Value>;
|
||
|
|
||
|
List();
|
||
|
|
||
|
List(List&&) noexcept;
|
||
|
List& operator=(List&&) noexcept;
|
||
|
|
||
|
// Deleted to prevent accidental copying.
|
||
|
List(const List&) = delete;
|
||
|
List& operator=(const List&) = delete;
|
||
|
|
||
|
~List();
|
||
|
|
||
|
// TODO(dcheng): Probably need to allow construction from a pair of
|
||
|
// iterators for now due to the prevalence of ListStorage now.
|
||
|
|
||
|
// Returns true if there are no values in this list and false otherwise.
|
||
|
bool empty() const;
|
||
|
|
||
|
// Returns the number of values in this list.
|
||
|
size_t size() const;
|
||
|
|
||
|
// Returns an iterator to the first value in this list.
|
||
|
iterator begin();
|
||
|
const_iterator begin() const;
|
||
|
const_iterator cbegin() const;
|
||
|
|
||
|
// Returns an iterator following the last value in this list. May not be
|
||
|
// dereferenced.
|
||
|
iterator end();
|
||
|
const_iterator end() const;
|
||
|
const_iterator cend() const;
|
||
|
|
||
|
// Returns a reference to the value at `index` in this list. Fails with a
|
||
|
// `CHECK()` if `index >= size()`.
|
||
|
const Value& operator[](size_t index) const;
|
||
|
Value& operator[](size_t index);
|
||
|
|
||
|
// Removes all value from this list.
|
||
|
void clear();
|
||
|
|
||
|
// Removes the value referenced by `pos` in this listand returns an iterator
|
||
|
// to the value following the removed value.
|
||
|
iterator erase(iterator pos);
|
||
|
const_iterator erase(const_iterator pos);
|
||
|
|
||
|
// Creates a deep copy of this dictionary.
|
||
|
List Clone() const;
|
||
|
|
||
|
// Appends `value` to the end of this list.
|
||
|
void Append(Value&& value);
|
||
|
void Append(bool value);
|
||
|
template <typename T>
|
||
|
void Append(const T*) = delete;
|
||
|
void Append(int value);
|
||
|
void Append(double value);
|
||
|
void Append(StringPiece value);
|
||
|
void Append(StringPiece16 value);
|
||
|
void Append(const char* value);
|
||
|
void Append(const char16_t* value);
|
||
|
void Append(std::string&& value);
|
||
|
void Append(BlobStorage&& value);
|
||
|
void Append(Dict&& value);
|
||
|
void Append(List&& value);
|
||
|
|
||
|
// Inserts `value` before `pos` in this list. Returns an iterator to the
|
||
|
// inserted value.
|
||
|
// TODO(dcheng): Should this provide the same set of overloads that Append()
|
||
|
// does?
|
||
|
iterator Insert(const_iterator pos, Value&& value);
|
||
|
|
||
|
// Erases all values equal to `value` from this list.
|
||
|
size_t EraseValue(const Value& value);
|
||
|
|
||
|
// Erases all values for which `predicate` evaluates to true from this list.
|
||
|
template <typename Predicate>
|
||
|
size_t EraseIf(Predicate predicate) {
|
||
|
return base::EraseIf(storage_, predicate);
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
BASE_EXPORT friend bool operator==(const List& lhs, const List& rhs);
|
||
|
BASE_EXPORT friend bool operator!=(const List& lhs, const List& rhs);
|
||
|
BASE_EXPORT friend bool operator<(const List& lhs, const List& rhs);
|
||
|
BASE_EXPORT friend bool operator>(const List& lhs, const List& rhs);
|
||
|
BASE_EXPORT friend bool operator<=(const List& lhs, const List& rhs);
|
||
|
BASE_EXPORT friend bool operator>=(const List& lhs, const List& rhs);
|
||
|
|
||
|
// For legacy access to the internal storage type.
|
||
|
friend Value;
|
||
|
|
||
|
explicit List(const std::vector<Value>& storage);
|
||
|
|
||
|
std::vector<Value> storage_;
|
||
|
};
|
||
|
|
||
|
// ===== DEPRECATED methods that require `type() == Type::LIST` =====
|
||
|
|
||
|
// Returns the Values in a list as a view. The mutable overload allows for
|
||
|
// modification of the underlying values, but does not allow changing the
|
||
|
// structure of the list. If this is desired, use `TakeListDeprecated()`,
|
||
|
// perform the operations, and return the list back to the Value via move
|
||
|
// assignment.
|
||
|
//
|
||
|
// DEPRECATED: prefer direct use `base::Value::List` where possible, or
|
||
|
// `GetList()` otherwise.
|
||
|
DeprecatedListView GetListDeprecated();
|
||
|
DeprecatedConstListView GetListDeprecated() const;
|
||
|
|
||
|
// Transfers ownership of the underlying list to the caller. Subsequent
|
||
|
// calls to `GetListDeprecated()` will return an empty list.
|
||
|
//
|
||
|
// DEPRECATED: prefer direct use of `base::Value::List` where possible, or
|
||
|
// `std::move(value.GetList())` otherwise.
|
||
|
DeprecatedListStorage TakeListDeprecated() &&;
|
||
|
|
||
|
// Appends `value` to the end of the list.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::List::Append()`.
|
||
|
void Append(Value&& value);
|
||
|
// DEPRECATED: prefer `Value::List::Append()`.
|
||
|
void Append(bool value);
|
||
|
template <typename T>
|
||
|
void Append(const T* ptr) = delete;
|
||
|
// DEPRECATED: prefer `Value::List::Append()`.
|
||
|
void Append(int value);
|
||
|
// DEPRECATED: prefer `Value::List::Append()`.
|
||
|
void Append(double value);
|
||
|
// DEPRECATED: prefer `Value::List::Append()`.
|
||
|
void Append(StringPiece value);
|
||
|
// DEPRECATED: prefer `Value::List::Append()`.
|
||
|
void Append(StringPiece16 value);
|
||
|
// DEPRECATED: prefer `Value::List::Append()`.
|
||
|
void Append(const char* value);
|
||
|
// DEPRECATED: prefer `Value::List::Append()`.
|
||
|
void Append(const char16_t* value);
|
||
|
// DEPRECATED: prefer `Value::List::Append()`.
|
||
|
void Append(std::string&& value);
|
||
|
|
||
|
// Inserts `value` before `pos`.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::List::Insert()`.
|
||
|
CheckedContiguousIterator<Value> Insert(
|
||
|
CheckedContiguousConstIterator<Value> pos,
|
||
|
Value&& value);
|
||
|
|
||
|
// Erases the Value pointed to by `iter`. Returns false if `iter` is out of
|
||
|
// bounds.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::List::erase(iter)`.
|
||
|
bool EraseListIter(CheckedContiguousConstIterator<Value> iter);
|
||
|
|
||
|
// Erases all Values that compare equal to `val`. Returns the number of
|
||
|
// deleted Values.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::List::EraseValue(val)`.
|
||
|
size_t EraseListValue(const Value& val);
|
||
|
|
||
|
// Erases all Values for which `pred` returns true. Returns the number of
|
||
|
// deleted Values.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::List::EraseIf(pred)`.
|
||
|
template <typename Predicate>
|
||
|
size_t EraseListValueIf(Predicate pred) {
|
||
|
return base::EraseIf(list(), pred);
|
||
|
}
|
||
|
|
||
|
// Erases all Values from the list.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::List::clear()`.
|
||
|
void ClearList();
|
||
|
|
||
|
// ===== DEPRECATED methods that require `type() == Type::DICT` =====
|
||
|
|
||
|
// `FindKey` looks up `key` in the underlying dictionary. If found, it returns
|
||
|
// a pointer to the element. Otherwise it returns nullptr.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::Dict::Find()`.
|
||
|
Value* FindKey(StringPiece key);
|
||
|
const Value* FindKey(StringPiece key) const;
|
||
|
|
||
|
// `FindKeyOfType` is similar to `FindKey`, but it also requires the found
|
||
|
// value to have type `type`. If no type is found, or the found value is of a
|
||
|
// different type nullptr is returned.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::Dict::FindBool()`, `Value::Dict::FindInt()`, et
|
||
|
// cetera.
|
||
|
Value* FindKeyOfType(StringPiece key, Type type);
|
||
|
const Value* FindKeyOfType(StringPiece key, Type type) const;
|
||
|
|
||
|
// These are convenience forms of `FindKey`. They return `absl::nullopt` or
|
||
|
// `nullptr` if the value is not found or doesn't have the type specified in
|
||
|
// the function's name.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::Dict::FindBool()`.
|
||
|
absl::optional<bool> FindBoolKey(StringPiece key) const;
|
||
|
// DEPRECATED: prefer `Value::Dict::FindInt()`.
|
||
|
absl::optional<int> FindIntKey(StringPiece key) const;
|
||
|
// Returns a non-null value for both `Value::Type::DOUBLE` and
|
||
|
// `Value::Type::INT`, converting the latter to a double.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::Dict::FindDouble()`.
|
||
|
absl::optional<double> FindDoubleKey(StringPiece key) const;
|
||
|
// DEPRECATED: prefer `Value::Dict::FindString()`.
|
||
|
const std::string* FindStringKey(StringPiece key) const;
|
||
|
std::string* FindStringKey(StringPiece key);
|
||
|
// DEPRECATED: prefer `Value::Dict::FindBlob()`.
|
||
|
const BlobStorage* FindBlobKey(StringPiece key) const;
|
||
|
// DEPRECATED: prefer `Value::Dict::FindDict()`.
|
||
|
const Value* FindDictKey(StringPiece key) const;
|
||
|
Value* FindDictKey(StringPiece key);
|
||
|
// DEPRECATED: prefer `Value::Dict::FindList()`.
|
||
|
const Value* FindListKey(StringPiece key) const;
|
||
|
Value* FindListKey(StringPiece key);
|
||
|
|
||
|
// `SetKey` looks up `key` in the underlying dictionary and sets the mapped
|
||
|
// value to `value`. If `key` could not be found, a new element is inserted.
|
||
|
// A pointer to the modified item is returned.
|
||
|
//
|
||
|
// Note: Prefer `Set<Type>Key()` if the input is not already a `Value`.
|
||
|
//
|
||
|
// DEPRECATED: Prefer `Value::Dict::Set()`.
|
||
|
Value* SetKey(StringPiece key, Value&& value);
|
||
|
|
||
|
// `Set`Type>Key` looks up `key` in the underlying dictionary and associates a
|
||
|
// corresponding Value() constructed from the second parameter. Compared to
|
||
|
// `SetKey()`, this avoids un-necessary temporary `Value()` creation, as well
|
||
|
// ambiguities in the value type.
|
||
|
//
|
||
|
// DEPRECATED: Prefer `Value::Dict::Set()`.
|
||
|
Value* SetBoolKey(StringPiece key, bool val);
|
||
|
// DEPRECATED: Prefer `Value::Dict::Set()`.
|
||
|
Value* SetIntKey(StringPiece key, int val);
|
||
|
// DEPRECATED: Prefer `Value::Dict::Set()`.
|
||
|
Value* SetDoubleKey(StringPiece key, double val);
|
||
|
// DEPRECATED: Prefer `Value::Dict::Set()`.
|
||
|
Value* SetStringKey(StringPiece key, StringPiece val);
|
||
|
// DEPRECATED: Prefer `Value::Dict::Set()`.
|
||
|
Value* SetStringKey(StringPiece key, StringPiece16 val);
|
||
|
// DEPRECATED: Prefer `Value::Dict::Set()`.
|
||
|
Value* SetStringKey(StringPiece key, const char* val);
|
||
|
// DEPRECATED: Prefer `Value::Dict::Set()`.
|
||
|
Value* SetStringKey(StringPiece key, std::string&& val);
|
||
|
|
||
|
// This attempts to remove the value associated with `key`. In case of
|
||
|
// failure, e.g. the key does not exist, false is returned and the underlying
|
||
|
// dictionary is not changed. In case of success, `key` is deleted from the
|
||
|
// dictionary and the method returns true.
|
||
|
//
|
||
|
// Deprecated: Prefer `Value::Dict::Remove()`.
|
||
|
bool RemoveKey(StringPiece key);
|
||
|
|
||
|
// This attempts to extract the value associated with `key`. In case of
|
||
|
// failure, e.g. the key does not exist, nullopt is returned and the
|
||
|
// underlying dictionary is not changed. In case of success, `key` is deleted
|
||
|
// from the dictionary and the method returns the extracted Value.
|
||
|
//
|
||
|
// DEPRECATED: Prefer `Value::Dict::Extract()`.
|
||
|
absl::optional<Value> ExtractKey(StringPiece key);
|
||
|
|
||
|
// Searches a hierarchy of dictionary values for a given value. If a path
|
||
|
// of dictionaries exist, returns the item at that path. If any of the path
|
||
|
// components do not exist or if any but the last path components are not
|
||
|
// dictionaries, returns nullptr. The type of the leaf Value is not checked.
|
||
|
//
|
||
|
// This version takes a StringPiece for the path, using dots as separators.
|
||
|
//
|
||
|
// DEPRECATED: Prefer `Value::Dict::FindByDottedPath()`.
|
||
|
Value* FindPath(StringPiece path);
|
||
|
const Value* FindPath(StringPiece path) const;
|
||
|
|
||
|
// There are also deprecated versions that take the path parameter
|
||
|
// as either a std::initializer_list<StringPiece> or a
|
||
|
// span<const StringPiece>. The latter is useful to use a
|
||
|
// std::vector<std::string> as a parameter but creates huge dynamic
|
||
|
// allocations and should be avoided!
|
||
|
// Note: If there is only one component in the path, use `FindKey()` instead.
|
||
|
//
|
||
|
// Example:
|
||
|
// std::vector<StringPiece> components = ...
|
||
|
// auto* found = FindPath(components);
|
||
|
//
|
||
|
// DEPRECATED: These are not common, and there is no currently planned
|
||
|
// replacement.
|
||
|
Value* FindPath(std::initializer_list<StringPiece> path);
|
||
|
Value* FindPath(span<const StringPiece> path);
|
||
|
const Value* FindPath(std::initializer_list<StringPiece> path) const;
|
||
|
const Value* FindPath(span<const StringPiece> path) const;
|
||
|
|
||
|
// Like FindPath() but will only return the value if the leaf Value type
|
||
|
// matches the given type. Will return nullptr otherwise.
|
||
|
// Note: Prefer `Find<Type>Path()` for simple values.
|
||
|
//
|
||
|
// Note: If there is only one component in the path, use `FindKeyOfType()`
|
||
|
// instead for slightly better performance.
|
||
|
//
|
||
|
// DEPRECATED: Use `Value::Dict::FindBoolByDottedPath()`,
|
||
|
// `Value::Dict::FindIntByDottedPath()`, et cetera.
|
||
|
Value* FindPathOfType(StringPiece path, Type type);
|
||
|
const Value* FindPathOfType(StringPiece path, Type type) const;
|
||
|
|
||
|
// Convenience accessors used when the expected type of a value is known.
|
||
|
// Similar to Find<Type>Key() but accepts paths instead of keys.
|
||
|
//
|
||
|
// DEPRECATED: Use `Value::Dict::FindBoolByDottedPath()`, or
|
||
|
// `Value::Dict::FindBool()` if the path only has one component, i.e. has no
|
||
|
// dots.
|
||
|
absl::optional<bool> FindBoolPath(StringPiece path) const;
|
||
|
// DEPRECATED: Use `Value::Dict::FindIntByDottedPath()`, or
|
||
|
// `Value::Dict::FindInt()` if the path only has one component, i.e. has no
|
||
|
// dots.
|
||
|
absl::optional<int> FindIntPath(StringPiece path) const;
|
||
|
// DEPRECATED: Use `Value::Dict::FindDoubleByDottedPath()`, or
|
||
|
// `Value::Dict::FindDouble()` if the path only has one component, i.e. has no
|
||
|
// dots.
|
||
|
absl::optional<double> FindDoublePath(StringPiece path) const;
|
||
|
// DEPRECATED: Use `Value::Dict::FindStringByDottedPath()`, or
|
||
|
// `Value::Dict::FindString()` if the path only has one component, i.e. has no
|
||
|
// dots.
|
||
|
const std::string* FindStringPath(StringPiece path) const;
|
||
|
std::string* FindStringPath(StringPiece path);
|
||
|
// DEPRECATED: Use `Value::Dict::FindBlobByDottedPath()`, or
|
||
|
// `Value::Dict::FindBlob()` if the path only has one component, i.e. has no
|
||
|
// dots.
|
||
|
const BlobStorage* FindBlobPath(StringPiece path) const;
|
||
|
// DEPRECATED: Use `Value::Dict::FindDictByDottedPath()`, or
|
||
|
// `Value::Dict::FindDict()` if the path only has one component, i.e. has no
|
||
|
// dots.
|
||
|
Value* FindDictPath(StringPiece path);
|
||
|
const Value* FindDictPath(StringPiece path) const;
|
||
|
// DEPRECATED: Use `Value::Dict::FindListByDottedPath()`, or
|
||
|
// `Value::Dict::FindList()` if the path only has one component, i.e. has no
|
||
|
// dots.
|
||
|
Value* FindListPath(StringPiece path);
|
||
|
const Value* FindListPath(StringPiece path) const;
|
||
|
|
||
|
// The following forms are deprecated too, use the ones that take the path
|
||
|
// as a single StringPiece instead.
|
||
|
//
|
||
|
// DEPRECATED: These are not common, and there is no currently planned
|
||
|
// replacement.
|
||
|
Value* FindPathOfType(std::initializer_list<StringPiece> path, Type type);
|
||
|
Value* FindPathOfType(span<const StringPiece> path, Type type);
|
||
|
const Value* FindPathOfType(std::initializer_list<StringPiece> path,
|
||
|
Type type) const;
|
||
|
const Value* FindPathOfType(span<const StringPiece> path, Type type) const;
|
||
|
|
||
|
// Sets the given path, expanding and creating dictionary keys as necessary.
|
||
|
//
|
||
|
// If the current value is not a dictionary, the function returns nullptr. If
|
||
|
// path components do not exist, they will be created. If any but the last
|
||
|
// components matches a value that is not a dictionary, the function will fail
|
||
|
// (it will not overwrite the value) and return nullptr. The last path
|
||
|
// component will be unconditionally overwritten if it exists, and created if
|
||
|
// it doesn't.
|
||
|
//
|
||
|
// Note: If there is only one component in the path, use `SetKey()` instead.
|
||
|
// Note: Using `Set<Type>Path()` might be more convenient and efficient.
|
||
|
//
|
||
|
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
|
||
|
Value* SetPath(StringPiece path, Value&& value);
|
||
|
|
||
|
// These setters are more convenient and efficient than the corresponding
|
||
|
// SetPath(...) call.
|
||
|
//
|
||
|
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
|
||
|
Value* SetBoolPath(StringPiece path, bool value);
|
||
|
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
|
||
|
Value* SetIntPath(StringPiece path, int value);
|
||
|
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
|
||
|
Value* SetDoublePath(StringPiece path, double value);
|
||
|
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
|
||
|
Value* SetStringPath(StringPiece path, StringPiece value);
|
||
|
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
|
||
|
Value* SetStringPath(StringPiece path, const char* value);
|
||
|
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
|
||
|
Value* SetStringPath(StringPiece path, std::string&& value);
|
||
|
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
|
||
|
Value* SetStringPath(StringPiece path, StringPiece16 value);
|
||
|
|
||
|
// DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
|
||
|
Value* SetPath(std::initializer_list<StringPiece> path, Value&& value);
|
||
|
Value* SetPath(span<const StringPiece> path, Value&& value);
|
||
|
|
||
|
// Tries to remove a Value at the given path.
|
||
|
//
|
||
|
// If the current value is not a dictionary or any path component does not
|
||
|
// exist, this operation fails, leaves underlying Values untouched and returns
|
||
|
// `false`. In case intermediate dictionaries become empty as a result of this
|
||
|
// path removal, they will be removed as well.
|
||
|
// Note: If there is only one component in the path, use `RemoveKey()`
|
||
|
// instead.
|
||
|
//
|
||
|
// DEPRECATED: Use `Value::Dict::RemoveByDottedPath()`.
|
||
|
bool RemovePath(StringPiece path);
|
||
|
|
||
|
// Tries to extract a Value at the given path.
|
||
|
//
|
||
|
// If the current value is not a dictionary or any path component does not
|
||
|
// exist, this operation fails, leaves underlying Values untouched and returns
|
||
|
// nullopt. In case intermediate dictionaries become empty as a result of this
|
||
|
// path removal, they will be removed as well. Returns the extracted value on
|
||
|
// success.
|
||
|
// Note: If there is only one component in the path, use `ExtractKey()`
|
||
|
// instead.
|
||
|
//
|
||
|
// DEPRECATED: Use `Value::Dict::ExtractByDottedPath()`.
|
||
|
absl::optional<Value> ExtractPath(StringPiece path);
|
||
|
|
||
|
using dict_iterator_proxy = detail::dict_iterator_proxy;
|
||
|
using const_dict_iterator_proxy = detail::const_dict_iterator_proxy;
|
||
|
|
||
|
// `DictItems` returns a proxy object that exposes iterators to the underlying
|
||
|
// dictionary. These are intended for iteration over all items in the
|
||
|
// dictionary and are compatible with for-each loops and standard library
|
||
|
// algorithms.
|
||
|
//
|
||
|
// Unlike with std::map, a range-for over the non-const version of
|
||
|
// `DictItems()` will range over items of type
|
||
|
// `pair<const std::string&, Value&>`, so code of the form
|
||
|
// for (auto kv : my_value.DictItems())
|
||
|
// Mutate(kv.second);
|
||
|
// will actually alter `my_value` in place (if it isn't const).
|
||
|
//
|
||
|
// DEPRECATED: Use a range-based for loop over `base::Value::Dict` directly
|
||
|
// instead.
|
||
|
dict_iterator_proxy DictItems();
|
||
|
const_dict_iterator_proxy DictItems() const;
|
||
|
|
||
|
// Transfers ownership of the underlying dict to the caller. Subsequent
|
||
|
// calls to DictItems() will return an empty dict.
|
||
|
//
|
||
|
// DEPRECATED: prefer direct use of `base::Value::Dict` where possible, or
|
||
|
// `std::move(value.GetDict())` otherwise.
|
||
|
DeprecatedDictStorage TakeDictDeprecated() &&;
|
||
|
|
||
|
// DEPRECATED: prefer `Value::Dict::size()`.
|
||
|
size_t DictSize() const;
|
||
|
|
||
|
// DEPRECATED: prefer `Value::Dict::empty()`.
|
||
|
bool DictEmpty() const;
|
||
|
|
||
|
// DEPRECATED: prefer `Value::Dict::clear()`.
|
||
|
void DictClear();
|
||
|
|
||
|
// Merge `dictionary` into this value. This is done recursively, i.e. any
|
||
|
// sub-dictionaries will be merged as well. In case of key collisions, the
|
||
|
// passed in dictionary takes precedence and data already present will be
|
||
|
// replaced. Values within `dictionary` are deep-copied, so `dictionary` may
|
||
|
// be freed any time after this call.
|
||
|
// Note: This requires that `type()` and `dictionary->type()` is
|
||
|
// Type::DICT.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::Dict::Merge()`.
|
||
|
void MergeDictionary(const Value* dictionary);
|
||
|
|
||
|
// These methods allow the convenient retrieval of the contents of the Value.
|
||
|
// If the current object can be converted into the given type, the value is
|
||
|
// returned through the `out_value` parameter and true is returned;
|
||
|
// otherwise, false is returned and `out_value` is unchanged.
|
||
|
// ListValue::From is the equivalent for std::unique_ptr conversions.
|
||
|
//
|
||
|
// DEPRECATED: prefer direct use `base::Value::List` where possible, or
|
||
|
// `GetIfList()` otherwise.
|
||
|
bool GetAsList(ListValue** out_value);
|
||
|
bool GetAsList(const ListValue** out_value) const;
|
||
|
// DictionaryValue::From is the equivalent for std::unique_ptr conversions.
|
||
|
//
|
||
|
// DEPRECATED: prefer direct use `base::Value::Dict` where possible, or
|
||
|
// `GetIfDict()` otherwise.
|
||
|
bool GetAsDictionary(DictionaryValue** out_value);
|
||
|
bool GetAsDictionary(const DictionaryValue** out_value) const;
|
||
|
// Note: Do not add more types. See the file-level comment above for why.
|
||
|
|
||
|
// This creates a deep copy of the entire Value tree, and returns a pointer
|
||
|
// to the copy. The caller gets ownership of the copy, of course.
|
||
|
// Subclasses return their own type directly in their overrides;
|
||
|
// this works because C++ supports covariant return types.
|
||
|
// TODO(crbug.com/646113): Delete this and migrate callsites.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::Clone()`.
|
||
|
std::unique_ptr<Value> CreateDeepCopy() const;
|
||
|
|
||
|
// Comparison operators so that Values can easily be used with standard
|
||
|
// library algorithms and associative containers.
|
||
|
BASE_EXPORT friend bool operator==(const Value& lhs, const Value& rhs);
|
||
|
BASE_EXPORT friend bool operator!=(const Value& lhs, const Value& rhs);
|
||
|
BASE_EXPORT friend bool operator<(const Value& lhs, const Value& rhs);
|
||
|
BASE_EXPORT friend bool operator>(const Value& lhs, const Value& rhs);
|
||
|
BASE_EXPORT friend bool operator<=(const Value& lhs, const Value& rhs);
|
||
|
BASE_EXPORT friend bool operator>=(const Value& lhs, const Value& rhs);
|
||
|
|
||
|
// Compares if two Value objects have equal contents.
|
||
|
// DEPRECATED, use `operator==(const Value& lhs, const Value& rhs)` instead.
|
||
|
// TODO(crbug.com/646113): Delete this and migrate callsites.
|
||
|
//
|
||
|
// DEPRECATED: prefer direct use of the equality operator instead.
|
||
|
bool Equals(const Value* other) const;
|
||
|
|
||
|
// Estimates dynamic memory usage. Requires tracing support
|
||
|
// (enable_base_tracing gn flag), otherwise always returns 0. See
|
||
|
// base/trace_event/memory_usage_estimator.h for more info.
|
||
|
size_t EstimateMemoryUsage() const;
|
||
|
|
||
|
// Serializes to a string for logging and debug purposes.
|
||
|
std::string DebugString() const;
|
||
|
|
||
|
#if BUILDFLAG(ENABLE_BASE_TRACING)
|
||
|
// Write this object into a trace.
|
||
|
void WriteIntoTrace(perfetto::TracedValue) const;
|
||
|
#endif // BUILDFLAG(ENABLE_BASE_TRACING)
|
||
|
|
||
|
template <typename Visitor>
|
||
|
auto Visit(Visitor&& visitor) const {
|
||
|
return absl::visit(std::forward<Visitor>(visitor), data_);
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
// Checked convenience accessors for dict and list.
|
||
|
const LegacyDictStorage& dict() const { return GetDict().storage_; }
|
||
|
LegacyDictStorage& dict() { return GetDict().storage_; }
|
||
|
const ListStorage& list() const { return GetList().storage_; }
|
||
|
ListStorage& list() { return GetList().storage_; }
|
||
|
|
||
|
// Internal constructors, allowing the simplify the implementation of Clone().
|
||
|
explicit Value(const LegacyDictStorage& storage);
|
||
|
explicit Value(LegacyDictStorage&& storage) noexcept;
|
||
|
|
||
|
private:
|
||
|
// For access to DoubleStorage.
|
||
|
friend class ValueView;
|
||
|
|
||
|
// Special case for doubles, which are aligned to 8 bytes on some
|
||
|
// 32-bit architectures. In this case, a simple declaration as a
|
||
|
// double member would make the whole union 8 byte-aligned, which
|
||
|
// would also force 4 bytes of wasted padding space before it in
|
||
|
// the Value layout.
|
||
|
//
|
||
|
// To override this, store the value as an array of 32-bit integers, and
|
||
|
// perform the appropriate bit casts when reading / writing to it.
|
||
|
class DoubleStorage {
|
||
|
public:
|
||
|
explicit DoubleStorage(double v);
|
||
|
DoubleStorage(const DoubleStorage&) = default;
|
||
|
DoubleStorage& operator=(const DoubleStorage&) = default;
|
||
|
|
||
|
// Provide an implicit conversion to double to simplify the use of visitors
|
||
|
// with `Value::Visit()`. Otherwise, visitors would need a branch for
|
||
|
// handling `DoubleStorage` like:
|
||
|
//
|
||
|
// value.Visit([] (const auto& member) {
|
||
|
// using T = std::decay_t<decltype(member)>;
|
||
|
// if constexpr (std::is_same_v<T, Value::DoubleStorage>) {
|
||
|
// SomeFunction(double{member});
|
||
|
// } else {
|
||
|
// SomeFunction(member);
|
||
|
// }
|
||
|
// });
|
||
|
operator double() const { return bit_cast<double>(v_); }
|
||
|
|
||
|
private:
|
||
|
friend bool operator==(const DoubleStorage& lhs, const DoubleStorage& rhs) {
|
||
|
return double{lhs} == double{rhs};
|
||
|
}
|
||
|
|
||
|
friend bool operator!=(const DoubleStorage& lhs, const DoubleStorage& rhs) {
|
||
|
return !(lhs == rhs);
|
||
|
}
|
||
|
|
||
|
friend bool operator<(const DoubleStorage& lhs, const DoubleStorage& rhs) {
|
||
|
return double{lhs} < double{rhs};
|
||
|
}
|
||
|
|
||
|
friend bool operator>(const DoubleStorage& lhs, const DoubleStorage& rhs) {
|
||
|
return rhs < lhs;
|
||
|
}
|
||
|
|
||
|
friend bool operator<=(const DoubleStorage& lhs, const DoubleStorage& rhs) {
|
||
|
return !(rhs < lhs);
|
||
|
}
|
||
|
|
||
|
friend bool operator>=(const DoubleStorage& lhs, const DoubleStorage& rhs) {
|
||
|
return !(lhs < rhs);
|
||
|
}
|
||
|
|
||
|
alignas(4) std::array<char, sizeof(double)> v_;
|
||
|
};
|
||
|
|
||
|
// Internal constructors, allowing the simplify the implementation of Clone().
|
||
|
explicit Value(absl::monostate);
|
||
|
explicit Value(DoubleStorage storage);
|
||
|
|
||
|
friend class ValuesTest_SizeOfValue_Test;
|
||
|
|
||
|
absl::variant<absl::monostate,
|
||
|
bool,
|
||
|
int,
|
||
|
DoubleStorage,
|
||
|
std::string,
|
||
|
BlobStorage,
|
||
|
Dict,
|
||
|
List>
|
||
|
data_;
|
||
|
};
|
||
|
|
||
|
// DictionaryValue provides a key-value dictionary with (optional) "path"
|
||
|
// parsing for recursive access; see the comment at the top of the file. Keys
|
||
|
// are std::string's and should be UTF-8 encoded.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::Dict`.
|
||
|
class BASE_EXPORT DictionaryValue : public Value {
|
||
|
public:
|
||
|
// Returns `value` if it is a dictionary, nullptr otherwise.
|
||
|
static std::unique_ptr<DictionaryValue> From(std::unique_ptr<Value> value);
|
||
|
|
||
|
DictionaryValue();
|
||
|
explicit DictionaryValue(const LegacyDictStorage& in_dict);
|
||
|
explicit DictionaryValue(LegacyDictStorage&& in_dict) noexcept;
|
||
|
|
||
|
// Returns true if the current dictionary has a value for the given key.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::Dict::contains()`.
|
||
|
bool HasKey(StringPiece key) const;
|
||
|
|
||
|
// Sets the Value associated with the given path starting from this object.
|
||
|
// A path has the form "<key>" or "<key>.<key>.[...]", where "." indexes
|
||
|
// into the next DictionaryValue down. Obviously, "." can't be used
|
||
|
// within a key, but there are no other restrictions on keys.
|
||
|
// If the key at any step of the way doesn't exist, or exists but isn't
|
||
|
// a DictionaryValue, a new DictionaryValue will be created and attached
|
||
|
// to the path in that location. `in_value` must be non-null.
|
||
|
// Returns a pointer to the inserted value.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
|
||
|
// component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
|
||
|
// otherwise.
|
||
|
Value* Set(StringPiece path, std::unique_ptr<Value> in_value);
|
||
|
|
||
|
// Convenience forms of Set(). These methods will replace any existing
|
||
|
// value at that path, even if it has a different type.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
|
||
|
// component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
|
||
|
// otherwise.
|
||
|
Value* SetBoolean(StringPiece path, bool in_value);
|
||
|
// DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
|
||
|
// component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
|
||
|
// otherwise.
|
||
|
Value* SetInteger(StringPiece path, int in_value);
|
||
|
// DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
|
||
|
// component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
|
||
|
// otherwise.
|
||
|
Value* SetDouble(StringPiece path, double in_value);
|
||
|
// DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
|
||
|
// component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
|
||
|
// otherwise.
|
||
|
Value* SetString(StringPiece path, StringPiece in_value);
|
||
|
// DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
|
||
|
// component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
|
||
|
// otherwise.
|
||
|
Value* SetString(StringPiece path, const std::u16string& in_value);
|
||
|
// DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
|
||
|
// component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
|
||
|
// otherwise.
|
||
|
ListValue* SetList(StringPiece path, std::unique_ptr<ListValue> in_value);
|
||
|
|
||
|
// Like Set(), but without special treatment of '.'. This allows e.g. URLs to
|
||
|
// be used as paths.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::Dict::Set()`.
|
||
|
Value* SetWithoutPathExpansion(StringPiece key,
|
||
|
std::unique_ptr<Value> in_value);
|
||
|
|
||
|
// Gets the Value associated with the given path starting from this object.
|
||
|
// A path has the form "<key>" or "<key>.<key>.[...]", where "." indexes
|
||
|
// into the next DictionaryValue down. If the path can be resolved
|
||
|
// successfully, the value for the last key in the path will be returned
|
||
|
// through the `out_value` parameter, and the function will return true.
|
||
|
// Otherwise, it will return false and `out_value` will be untouched.
|
||
|
// Note that the dictionary always owns the value that's returned.
|
||
|
// `out_value` is optional and will only be set if non-NULL.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::Dict::Find()` (if the path only has one
|
||
|
// component, i.e. has no dots), or `Value::Dict::FindByDottedPath()`
|
||
|
// otherwise.
|
||
|
bool Get(StringPiece path, const Value** out_value) const;
|
||
|
bool Get(StringPiece path, Value** out_value);
|
||
|
|
||
|
// These are convenience forms of `Get()`. The value will be retrieved
|
||
|
// and the return value will be true if the path is valid and the value at
|
||
|
// the end of the path can be returned in the form specified.
|
||
|
// `out_value` is optional and will only be set if non-NULL.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::Dict::FindInt()` (if the path only has one
|
||
|
// component, i.e. has no dots), or `Value::Dict::FindIntByDottedPath()`
|
||
|
// otherwise.
|
||
|
bool GetInteger(StringPiece path, int* out_value) const;
|
||
|
// DEPRECATED: prefer `Value::Dict::FindString()` (if the path only has one
|
||
|
// component, i.e. has no dots), or `Value::Dict::FindStringByDottedPath()`
|
||
|
// otherwise.
|
||
|
bool GetString(StringPiece path, std::string* out_value) const;
|
||
|
bool GetString(StringPiece path, std::u16string* out_value) const;
|
||
|
// DEPRECATED: prefer `Value::Dict::FindDict()` (if the path only has one
|
||
|
// component, i.e. has no dots), or `Value::Dict::FindDictByDottedPath()`
|
||
|
// otherwise.
|
||
|
bool GetDictionary(StringPiece path, const DictionaryValue** out_value) const;
|
||
|
bool GetDictionary(StringPiece path, DictionaryValue** out_value);
|
||
|
// DEPRECATED: prefer `Value::Dict::FindList()` (if the path only has one
|
||
|
// component, i.e. has no dots), or `Value::Dict::FindListByDottedPath()`
|
||
|
// otherwise.
|
||
|
bool GetList(StringPiece path, const ListValue** out_value) const;
|
||
|
bool GetList(StringPiece path, ListValue** out_value);
|
||
|
|
||
|
// Like `Get()`, but without special treatment of '.'. This allows e.g. URLs
|
||
|
// to be used as paths.
|
||
|
// DEPRECATED, use `Value::FindDictKey(key)` instead.
|
||
|
bool GetDictionaryWithoutPathExpansion(
|
||
|
StringPiece key,
|
||
|
const DictionaryValue** out_value) const;
|
||
|
// DEPRECATED, use `Value::FindDictKey(key)` instead.
|
||
|
bool GetDictionaryWithoutPathExpansion(StringPiece key,
|
||
|
DictionaryValue** out_value);
|
||
|
// DEPRECATED, use `Value::FindListKey(key)` instead.
|
||
|
bool GetListWithoutPathExpansion(StringPiece key,
|
||
|
const ListValue** out_value) const;
|
||
|
// DEPRECATED, use `Value::FindListKey(key)` instead.
|
||
|
bool GetListWithoutPathExpansion(StringPiece key, ListValue** out_value);
|
||
|
|
||
|
// Makes a copy of `this` but doesn't include empty dictionaries and lists in
|
||
|
// the copy. This never returns NULL, even if `this` itself is empty.
|
||
|
std::unique_ptr<DictionaryValue> DeepCopyWithoutEmptyChildren() const;
|
||
|
|
||
|
// Swaps contents with the `other` dictionary.
|
||
|
void Swap(DictionaryValue* other);
|
||
|
|
||
|
// This class provides an iterator over both keys and values in the
|
||
|
// dictionary. It can't be used to modify the dictionary.
|
||
|
//
|
||
|
// DEPRECATED: Use a range-based for loop over `base::Value::Dict` directly
|
||
|
// instead.
|
||
|
class BASE_EXPORT Iterator {
|
||
|
public:
|
||
|
explicit Iterator(const DictionaryValue& target);
|
||
|
Iterator(const Iterator& other);
|
||
|
~Iterator();
|
||
|
|
||
|
bool IsAtEnd() const { return it_ == target_.DictItems().end(); }
|
||
|
void Advance() { ++it_; }
|
||
|
|
||
|
const std::string& key() const { return it_->first; }
|
||
|
const Value& value() const { return it_->second; }
|
||
|
|
||
|
private:
|
||
|
const DictionaryValue& target_;
|
||
|
detail::const_dict_iterator it_;
|
||
|
};
|
||
|
|
||
|
// DEPRECATED, use `Value::Dict::Clone()` instead.
|
||
|
// TODO(crbug.com/646113): Delete this and migrate callsites.
|
||
|
DictionaryValue* DeepCopy() const;
|
||
|
// DEPRECATED, use `Value::Dict::Clone()` instead.
|
||
|
// TODO(crbug.com/646113): Delete this and migrate callsites.
|
||
|
std::unique_ptr<DictionaryValue> CreateDeepCopy() const;
|
||
|
};
|
||
|
|
||
|
// This type of Value represents a list of other Value values.
|
||
|
//
|
||
|
// DEPRECATED: prefer `base::Value::List`.
|
||
|
class BASE_EXPORT ListValue : public Value {
|
||
|
public:
|
||
|
using const_iterator = ListView::const_iterator;
|
||
|
using iterator = ListView::iterator;
|
||
|
|
||
|
// Returns `value` if it is a list, nullptr otherwise.
|
||
|
static std::unique_ptr<ListValue> From(std::unique_ptr<Value> value);
|
||
|
|
||
|
ListValue();
|
||
|
explicit ListValue(span<const Value> in_list);
|
||
|
explicit ListValue(ListStorage&& in_list) noexcept;
|
||
|
|
||
|
// Convenience forms of `Get()`. Modifies `out_value` (and returns true)
|
||
|
// only if the index is valid and the Value at that index can be returned
|
||
|
// in the specified form.
|
||
|
// `out_value` is optional and will only be set if non-NULL.
|
||
|
//
|
||
|
// DEPRECATED: prefer `Value::List::operator[]` + `GetIfDict()`.
|
||
|
bool GetDictionary(size_t index, const DictionaryValue** out_value) const;
|
||
|
bool GetDictionary(size_t index, DictionaryValue** out_value);
|
||
|
|
||
|
// Appends a Value to the end of the list.
|
||
|
// DEPRECATED: prefer `Value::List::Append()`.
|
||
|
using Value::Append;
|
||
|
// DEPRECATED: prefer `Value::List::Append()`.
|
||
|
void Append(std::unique_ptr<Value> in_value);
|
||
|
|
||
|
// Swaps contents with the `other` list.
|
||
|
//
|
||
|
// DEPRECATED: prefer `base::Value::List` + `std::swap()`.
|
||
|
void Swap(ListValue* other);
|
||
|
|
||
|
// Iteration: Use a range-based for loop over `base::Value::List` directly
|
||
|
// instead.
|
||
|
};
|
||
|
|
||
|
// 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 `StringPiece` 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 {
|
||
|
public:
|
||
|
ValueView(bool value) : data_view_(value) {}
|
||
|
ValueView(int value) : data_view_(value) {}
|
||
|
ValueView(double value)
|
||
|
: data_view_(absl::in_place_type_t<Value::DoubleStorage>(), value) {}
|
||
|
ValueView(const std::string& value) : data_view_(value) {}
|
||
|
ValueView(const Value::BlobStorage& value) : data_view_(value) {}
|
||
|
ValueView(const Value::Dict& value) : data_view_(value) {}
|
||
|
ValueView(const Value::List& value) : data_view_(value) {}
|
||
|
ValueView(const Value& value);
|
||
|
|
||
|
template <typename Visitor>
|
||
|
auto Visit(Visitor&& visitor) const {
|
||
|
return absl::visit(std::forward<Visitor>(visitor), data_view_);
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
using ViewType =
|
||
|
absl::variant<absl::monostate,
|
||
|
bool,
|
||
|
int,
|
||
|
Value::DoubleStorage,
|
||
|
std::reference_wrapper<const std::string>,
|
||
|
std::reference_wrapper<const Value::BlobStorage>,
|
||
|
std::reference_wrapper<const Value::Dict>,
|
||
|
std::reference_wrapper<const Value::List>>;
|
||
|
|
||
|
ViewType data_view_;
|
||
|
};
|
||
|
|
||
|
// This interface is implemented by classes that know how to serialize
|
||
|
// Value objects.
|
||
|
class BASE_EXPORT ValueSerializer {
|
||
|
public:
|
||
|
virtual ~ValueSerializer();
|
||
|
|
||
|
virtual bool Serialize(ValueView root) = 0;
|
||
|
};
|
||
|
|
||
|
// This interface is implemented by classes that know how to deserialize Value
|
||
|
// objects.
|
||
|
class BASE_EXPORT ValueDeserializer {
|
||
|
public:
|
||
|
virtual ~ValueDeserializer();
|
||
|
|
||
|
// This method deserializes the subclass-specific format into a Value object.
|
||
|
// If the return value is non-NULL, the caller takes ownership of returned
|
||
|
// Value.
|
||
|
//
|
||
|
// If the return value is nullptr, and if `error_code` is non-nullptr,
|
||
|
// `*error_code` will be set to an integer value representing the underlying
|
||
|
// error. See "enum ErrorCode" below for more detail about the integer value.
|
||
|
//
|
||
|
// If `error_message` is non-nullptr, it will be filled in with a formatted
|
||
|
// error message including the location of the error if appropriate.
|
||
|
virtual std::unique_ptr<Value> Deserialize(int* error_code,
|
||
|
std::string* error_message) = 0;
|
||
|
|
||
|
// The integer-valued error codes form four groups:
|
||
|
// - The value 0 means no error.
|
||
|
// - Values between 1 and 999 inclusive mean an error in the data (i.e.
|
||
|
// content). The bytes being deserialized are not in the right format.
|
||
|
// - Values 1000 and above mean an error in the metadata (i.e. context). The
|
||
|
// file could not be read, the network is down, etc.
|
||
|
// - Negative values are reserved.
|
||
|
//
|
||
|
// These values are persisted to logs. Entries should not be renumbered and
|
||
|
// numeric values should never be reused.
|
||
|
enum ErrorCode {
|
||
|
kErrorCodeNoError = 0,
|
||
|
// kErrorCodeInvalidFormat is a generic error code for "the data is not in
|
||
|
// the right format". Subclasses of ValueDeserializer may return other
|
||
|
// values for more specific errors.
|
||
|
kErrorCodeInvalidFormat = 1,
|
||
|
// kErrorCodeFirstMetadataError is the minimum value (inclusive) of the
|
||
|
// range of metadata errors.
|
||
|
kErrorCodeFirstMetadataError = 1000,
|
||
|
};
|
||
|
|
||
|
// The `error_code` argument can be one of the ErrorCode values, but it is
|
||
|
// not restricted to only being 0, 1 or 1000. Subclasses of ValueDeserializer
|
||
|
// can define their own error code values.
|
||
|
static inline bool ErrorCodeIsDataError(int error_code) {
|
||
|
return (kErrorCodeInvalidFormat <= error_code) &&
|
||
|
(error_code < kErrorCodeFirstMetadataError);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// 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);
|
||
|
|
||
|
// Hints for DictionaryValue and ListValue; otherwise, gtest tends to prefer the
|
||
|
// default template implementation over an upcast to Value.
|
||
|
BASE_EXPORT inline std::ostream& operator<<(std::ostream& out,
|
||
|
const DictionaryValue& value) {
|
||
|
return out << static_cast<const Value&>(value);
|
||
|
}
|
||
|
|
||
|
BASE_EXPORT inline std::ostream& operator<<(std::ostream& out,
|
||
|
const ListValue& value) {
|
||
|
return out << static_cast<const Value&>(value);
|
||
|
}
|
||
|
|
||
|
// 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_
|