1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/values.h"
15 #include "base/json/json_writer.h"
16 #include "base/logging.h"
17 #include "base/memory/ptr_util.h"
18 #include "base/stl_util.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/trace_event/memory_usage_estimator.h"
27 const char* const kTypeNames[] = {"null", "boolean", "integer", "double",
28 "string", "binary", "dictionary", "list"};
29 static_assert(base::size(kTypeNames) ==
30 static_cast<size_t>(Value::Type::LIST) + 1,
31 "kTypeNames Has Wrong Size");
33 std::unique_ptr<Value> CopyWithoutEmptyChildren(const Value& node);
35 // Make a deep copy of |node|, but don't include empty lists or dictionaries
36 // in the copy. It's possible for this function to return NULL and it
37 // expects |node| to always be non-NULL.
38 std::unique_ptr<Value> CopyListWithoutEmptyChildren(const Value& list) {
39 Value copy(Value::Type::LIST);
40 for (const auto& entry : list.GetList()) {
41 std::unique_ptr<Value> child_copy = CopyWithoutEmptyChildren(entry);
43 copy.GetList().push_back(std::move(*child_copy));
45 return copy.GetList().empty() ? nullptr
46 : std::make_unique<Value>(std::move(copy));
49 std::unique_ptr<DictionaryValue> CopyDictionaryWithoutEmptyChildren(
50 const DictionaryValue& dict) {
51 std::unique_ptr<DictionaryValue> copy;
52 for (DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
53 std::unique_ptr<Value> child_copy = CopyWithoutEmptyChildren(it.value());
56 copy = std::make_unique<DictionaryValue>();
57 copy->SetWithoutPathExpansion(it.key(), std::move(child_copy));
63 std::unique_ptr<Value> CopyWithoutEmptyChildren(const Value& node) {
64 switch (node.type()) {
65 case Value::Type::LIST:
66 return CopyListWithoutEmptyChildren(static_cast<const ListValue&>(node));
68 case Value::Type::DICTIONARY:
69 return CopyDictionaryWithoutEmptyChildren(
70 static_cast<const DictionaryValue&>(node));
73 return std::make_unique<Value>(node.Clone());
79 constexpr uint32_t Value::kMagicIsAlive;
82 std::unique_ptr<Value> Value::CreateWithCopiedBuffer(const char* buffer,
84 return std::make_unique<Value>(BlobStorage(buffer, buffer + size));
88 Value Value::FromUniquePtrValue(std::unique_ptr<Value> val) {
89 return std::move(*val);
93 std::unique_ptr<Value> Value::ToUniquePtrValue(Value val) {
94 return std::make_unique<Value>(std::move(val));
97 Value::Value(Value&& that) noexcept {
98 InternalMoveConstructFrom(std::move(that));
101 Value::Value() noexcept : type_(Type::NONE) {}
103 Value::Value(Type type) : type_(type) {
104 // Initialize with the default value.
119 new (&string_value_) std::string();
122 new (&binary_value_) BlobStorage();
124 case Type::DICTIONARY:
125 new (&dict_) DictStorage();
128 new (&list_) ListStorage();
133 Value::Value(bool in_bool) : type_(Type::BOOLEAN), bool_value_(in_bool) {}
135 Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {}
137 Value::Value(double in_double) : type_(Type::DOUBLE), double_value_(in_double) {
138 if (!std::isfinite(double_value_)) {
139 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
140 << "values cannot be represented in JSON";
145 Value::Value(const char* in_string) : Value(std::string(in_string)) {}
147 Value::Value(StringPiece in_string) : Value(std::string(in_string)) {}
149 Value::Value(std::string&& in_string) noexcept
150 : type_(Type::STRING), string_value_(std::move(in_string)) {
151 DCHECK(IsStringUTF8(string_value_));
154 Value::Value(const char16* in_string16) : Value(StringPiece16(in_string16)) {}
156 Value::Value(StringPiece16 in_string16) : Value(UTF16ToUTF8(in_string16)) {}
158 Value::Value(const std::vector<char>& in_blob)
159 : type_(Type::BINARY), binary_value_(in_blob.begin(), in_blob.end()) {}
161 Value::Value(base::span<const uint8_t> in_blob)
162 : type_(Type::BINARY), binary_value_(in_blob.begin(), in_blob.end()) {}
164 Value::Value(BlobStorage&& in_blob) noexcept
165 : type_(Type::BINARY), binary_value_(std::move(in_blob)) {}
167 Value::Value(const DictStorage& in_dict) : type_(Type::DICTIONARY), dict_() {
168 dict_.reserve(in_dict.size());
169 for (const auto& it : in_dict) {
170 dict_.try_emplace(dict_.end(), it.first,
171 std::make_unique<Value>(it.second->Clone()));
175 Value::Value(DictStorage&& in_dict) noexcept
176 : type_(Type::DICTIONARY), dict_(std::move(in_dict)) {}
178 Value::Value(const ListStorage& in_list) : type_(Type::LIST), list_() {
179 list_.reserve(in_list.size());
180 for (const auto& val : in_list)
181 list_.emplace_back(val.Clone());
184 Value::Value(ListStorage&& in_list) noexcept
185 : type_(Type::LIST), list_(std::move(in_list)) {}
187 Value& Value::operator=(Value&& that) noexcept {
189 InternalMoveConstructFrom(std::move(that));
194 Value Value::Clone() const {
199 return Value(bool_value_);
201 return Value(int_value_);
203 return Value(double_value_);
205 return Value(string_value_);
207 return Value(binary_value_);
208 case Type::DICTIONARY:
224 const char* Value::GetTypeName(Value::Type type) {
225 DCHECK_GE(static_cast<int>(type), 0);
226 DCHECK_LT(static_cast<size_t>(type), base::size(kTypeNames));
227 return kTypeNames[static_cast<size_t>(type)];
230 bool Value::GetBool() const {
235 int Value::GetInt() const {
240 double Value::GetDouble() const {
242 return double_value_;
249 const std::string& Value::GetString() const {
251 return string_value_;
254 const Value::BlobStorage& Value::GetBlob() const {
256 return binary_value_;
259 Value::ListStorage& Value::GetList() {
264 const Value::ListStorage& Value::GetList() const {
269 Value* Value::FindKey(StringPiece key) {
270 return const_cast<Value*>(static_cast<const Value*>(this)->FindKey(key));
273 const Value* Value::FindKey(StringPiece key) const {
275 auto found = dict_.find(key);
276 if (found == dict_.end())
278 return found->second.get();
281 Value* Value::FindKeyOfType(StringPiece key, Type type) {
282 return const_cast<Value*>(
283 static_cast<const Value*>(this)->FindKeyOfType(key, type));
286 const Value* Value::FindKeyOfType(StringPiece key, Type type) const {
287 const Value* result = FindKey(key);
288 if (!result || result->type() != type)
293 base::Optional<bool> Value::FindBoolKey(StringPiece key) const {
294 const Value* result = FindKeyOfType(key, Type::BOOLEAN);
295 return result ? base::make_optional(result->bool_value_) : base::nullopt;
298 base::Optional<int> Value::FindIntKey(StringPiece key) const {
299 const Value* result = FindKeyOfType(key, Type::INTEGER);
300 return result ? base::make_optional(result->int_value_) : base::nullopt;
303 base::Optional<double> Value::FindDoubleKey(StringPiece key) const {
304 const Value* result = FindKeyOfType(key, Type::DOUBLE);
305 return result ? base::make_optional(result->double_value_) : base::nullopt;
308 const std::string* Value::FindStringKey(StringPiece key) const {
309 const Value* result = FindKeyOfType(key, Type::STRING);
310 return result ? &result->string_value_ : nullptr;
313 bool Value::RemoveKey(StringPiece key) {
315 // NOTE: Can't directly return dict_->erase(key) due to MSVC warning C4800.
316 return dict_.erase(key) != 0;
319 Value* Value::SetKey(StringPiece key, Value value) {
321 // NOTE: We can't use |insert_or_assign| here, as only |try_emplace| does
322 // an explicit conversion from StringPiece to std::string if necessary.
323 auto val_ptr = std::make_unique<Value>(std::move(value));
324 auto result = dict_.try_emplace(key, std::move(val_ptr));
325 if (!result.second) {
326 // val_ptr is guaranteed to be still intact at this point.
327 result.first->second = std::move(val_ptr);
329 return result.first->second.get();
332 Value* Value::SetKey(std::string&& key, Value value) {
335 .insert_or_assign(std::move(key),
336 std::make_unique<Value>(std::move(value)))
337 .first->second.get();
340 Value* Value::SetKey(const char* key, Value value) {
341 return SetKey(StringPiece(key), std::move(value));
344 Value* Value::FindPath(std::initializer_list<StringPiece> path) {
345 return const_cast<Value*>(const_cast<const Value*>(this)->FindPath(path));
348 Value* Value::FindPath(span<const StringPiece> path) {
349 return const_cast<Value*>(const_cast<const Value*>(this)->FindPath(path));
352 const Value* Value::FindPath(std::initializer_list<StringPiece> path) const {
353 DCHECK_GE(path.size(), 2u) << "Use FindKey() for a path of length 1.";
354 return FindPath(make_span(path.begin(), path.size()));
357 const Value* Value::FindPath(span<const StringPiece> path) const {
358 const Value* cur = this;
359 for (const StringPiece component : path) {
360 if (!cur->is_dict() || (cur = cur->FindKey(component)) == nullptr)
366 Value* Value::FindPathOfType(std::initializer_list<StringPiece> path,
368 return const_cast<Value*>(
369 const_cast<const Value*>(this)->FindPathOfType(path, type));
372 Value* Value::FindPathOfType(span<const StringPiece> path, Type type) {
373 return const_cast<Value*>(
374 const_cast<const Value*>(this)->FindPathOfType(path, type));
377 const Value* Value::FindPathOfType(std::initializer_list<StringPiece> path,
379 DCHECK_GE(path.size(), 2u) << "Use FindKeyOfType() for a path of length 1.";
380 return FindPathOfType(make_span(path.begin(), path.size()), type);
383 const Value* Value::FindPathOfType(span<const StringPiece> path,
385 const Value* result = FindPath(path);
386 if (!result || result->type() != type)
391 Value* Value::SetPath(std::initializer_list<StringPiece> path, Value value) {
392 DCHECK_GE(path.size(), 2u) << "Use SetKey() for a path of length 1.";
393 return SetPath(make_span(path.begin(), path.size()), std::move(value));
396 Value* Value::SetPath(span<const StringPiece> path, Value value) {
397 DCHECK(path.begin() != path.end()); // Can't be empty path.
399 // Walk/construct intermediate dictionaries. The last element requires
400 // special handling so skip it in this loop.
402 auto cur_path = path.begin();
403 for (; (cur_path + 1) < path.end(); ++cur_path) {
407 // Use lower_bound to avoid doing the search twice for missing keys.
408 const StringPiece path_component = *cur_path;
409 auto found = cur->dict_.lower_bound(path_component);
410 if (found == cur->dict_.end() || found->first != path_component) {
411 // No key found, insert one.
412 auto inserted = cur->dict_.try_emplace(
413 found, path_component, std::make_unique<Value>(Type::DICTIONARY));
414 cur = inserted->second.get();
416 cur = found->second.get();
420 // "cur" will now contain the last dictionary to insert or replace into.
423 return cur->SetKey(*cur_path, std::move(value));
426 bool Value::RemovePath(std::initializer_list<StringPiece> path) {
427 DCHECK_GE(path.size(), 2u) << "Use RemoveKey() for a path of length 1.";
428 return RemovePath(make_span(path.begin(), path.size()));
431 bool Value::RemovePath(span<const StringPiece> path) {
432 if (!is_dict() || path.empty())
435 if (path.size() == 1)
436 return RemoveKey(path[0]);
438 auto found = dict_.find(path[0]);
439 if (found == dict_.end() || !found->second->is_dict())
442 bool removed = found->second->RemovePath(path.subspan(1));
443 if (removed && found->second->dict_.empty())
449 Value::dict_iterator_proxy Value::DictItems() {
451 return dict_iterator_proxy(&dict_);
454 Value::const_dict_iterator_proxy Value::DictItems() const {
456 return const_dict_iterator_proxy(&dict_);
459 size_t Value::DictSize() const {
464 bool Value::DictEmpty() const {
466 return dict_.empty();
469 void Value::MergeDictionary(const Value* dictionary) {
471 CHECK(dictionary->is_dict());
472 for (const auto& pair : dictionary->dict_) {
473 const auto& key = pair.first;
474 const auto& val = pair.second;
475 // Check whether we have to merge dictionaries.
476 if (val->is_dict()) {
477 auto found = dict_.find(key);
478 if (found != dict_.end() && found->second->is_dict()) {
479 found->second->MergeDictionary(val.get());
484 // All other cases: Make a copy and hook it up.
485 SetKey(key, val->Clone());
489 bool Value::GetAsBoolean(bool* out_value) const {
490 if (out_value && is_bool()) {
491 *out_value = bool_value_;
497 bool Value::GetAsInteger(int* out_value) const {
498 if (out_value && is_int()) {
499 *out_value = int_value_;
505 bool Value::GetAsDouble(double* out_value) const {
506 if (out_value && is_double()) {
507 *out_value = double_value_;
510 if (out_value && is_int()) {
511 // Allow promotion from int to double.
512 *out_value = int_value_;
515 return is_double() || is_int();
518 bool Value::GetAsString(std::string* out_value) const {
519 if (out_value && is_string()) {
520 *out_value = string_value_;
526 bool Value::GetAsString(string16* out_value) const {
527 if (out_value && is_string()) {
528 *out_value = UTF8ToUTF16(string_value_);
534 bool Value::GetAsString(const Value** out_value) const {
535 if (out_value && is_string()) {
536 *out_value = static_cast<const Value*>(this);
542 bool Value::GetAsString(StringPiece* out_value) const {
543 if (out_value && is_string()) {
544 *out_value = string_value_;
550 bool Value::GetAsList(ListValue** out_value) {
551 if (out_value && is_list()) {
552 *out_value = static_cast<ListValue*>(this);
558 bool Value::GetAsList(const ListValue** out_value) const {
559 if (out_value && is_list()) {
560 *out_value = static_cast<const ListValue*>(this);
566 bool Value::GetAsDictionary(DictionaryValue** out_value) {
567 if (out_value && is_dict()) {
568 *out_value = static_cast<DictionaryValue*>(this);
574 bool Value::GetAsDictionary(const DictionaryValue** out_value) const {
575 if (out_value && is_dict()) {
576 *out_value = static_cast<const DictionaryValue*>(this);
582 Value* Value::DeepCopy() const {
583 return new Value(Clone());
586 std::unique_ptr<Value> Value::CreateDeepCopy() const {
587 return std::make_unique<Value>(Clone());
590 bool operator==(const Value& lhs, const Value& rhs) {
591 if (lhs.type_ != rhs.type_)
595 case Value::Type::NONE:
597 case Value::Type::BOOLEAN:
598 return lhs.bool_value_ == rhs.bool_value_;
599 case Value::Type::INTEGER:
600 return lhs.int_value_ == rhs.int_value_;
601 case Value::Type::DOUBLE:
602 return lhs.double_value_ == rhs.double_value_;
603 case Value::Type::STRING:
604 return lhs.string_value_ == rhs.string_value_;
605 case Value::Type::BINARY:
606 return lhs.binary_value_ == rhs.binary_value_;
607 // TODO(crbug.com/646113): Clean this up when DictionaryValue and ListValue
608 // are completely inlined.
609 case Value::Type::DICTIONARY:
610 if (lhs.dict_.size() != rhs.dict_.size())
612 return std::equal(std::begin(lhs.dict_), std::end(lhs.dict_),
613 std::begin(rhs.dict_),
614 [](const auto& u, const auto& v) {
615 return std::tie(u.first, *u.second) ==
616 std::tie(v.first, *v.second);
618 case Value::Type::LIST:
619 return lhs.list_ == rhs.list_;
626 bool operator!=(const Value& lhs, const Value& rhs) {
627 return !(lhs == rhs);
630 bool operator<(const Value& lhs, const Value& rhs) {
631 if (lhs.type_ != rhs.type_)
632 return lhs.type_ < rhs.type_;
635 case Value::Type::NONE:
637 case Value::Type::BOOLEAN:
638 return lhs.bool_value_ < rhs.bool_value_;
639 case Value::Type::INTEGER:
640 return lhs.int_value_ < rhs.int_value_;
641 case Value::Type::DOUBLE:
642 return lhs.double_value_ < rhs.double_value_;
643 case Value::Type::STRING:
644 return lhs.string_value_ < rhs.string_value_;
645 case Value::Type::BINARY:
646 return lhs.binary_value_ < rhs.binary_value_;
647 // TODO(crbug.com/646113): Clean this up when DictionaryValue and ListValue
648 // are completely inlined.
649 case Value::Type::DICTIONARY:
650 return std::lexicographical_compare(
651 std::begin(lhs.dict_), std::end(lhs.dict_), std::begin(rhs.dict_),
653 [](const Value::DictStorage::value_type& u,
654 const Value::DictStorage::value_type& v) {
655 return std::tie(u.first, *u.second) < std::tie(v.first, *v.second);
657 case Value::Type::LIST:
658 return lhs.list_ < rhs.list_;
665 bool operator>(const Value& lhs, const Value& rhs) {
669 bool operator<=(const Value& lhs, const Value& rhs) {
673 bool operator>=(const Value& lhs, const Value& rhs) {
677 bool Value::Equals(const Value* other) const {
679 return *this == *other;
682 size_t Value::EstimateMemoryUsage() const {
685 return base::trace_event::EstimateMemoryUsage(string_value_);
687 return base::trace_event::EstimateMemoryUsage(binary_value_);
688 case Type::DICTIONARY:
689 return base::trace_event::EstimateMemoryUsage(dict_);
691 return base::trace_event::EstimateMemoryUsage(list_);
697 void Value::InternalMoveConstructFrom(Value&& that) {
704 bool_value_ = that.bool_value_;
707 int_value_ = that.int_value_;
710 double_value_ = that.double_value_;
713 new (&string_value_) std::string(std::move(that.string_value_));
716 new (&binary_value_) BlobStorage(std::move(that.binary_value_));
718 case Type::DICTIONARY:
719 new (&dict_) DictStorage(std::move(that.dict_));
722 new (&list_) ListStorage(std::move(that.list_));
727 void Value::InternalCleanup() {
728 CHECK_EQ(is_alive_, kMagicIsAlive);
739 string_value_.~basic_string();
742 binary_value_.~BlobStorage();
744 case Type::DICTIONARY:
745 dict_.~DictStorage();
748 list_.~ListStorage();
753 ///////////////////// DictionaryValue ////////////////////
756 std::unique_ptr<DictionaryValue> DictionaryValue::From(
757 std::unique_ptr<Value> value) {
758 DictionaryValue* out;
759 if (value && value->GetAsDictionary(&out)) {
760 ignore_result(value.release());
761 return WrapUnique(out);
766 DictionaryValue::DictionaryValue() : Value(Type::DICTIONARY) {}
767 DictionaryValue::DictionaryValue(const DictStorage& in_dict) : Value(in_dict) {}
768 DictionaryValue::DictionaryValue(DictStorage&& in_dict) noexcept
769 : Value(std::move(in_dict)) {}
771 bool DictionaryValue::HasKey(StringPiece key) const {
772 DCHECK(IsStringUTF8(key));
773 auto current_entry = dict_.find(key);
774 DCHECK((current_entry == dict_.end()) || current_entry->second);
775 return current_entry != dict_.end();
778 void DictionaryValue::Clear() {
782 Value* DictionaryValue::Set(StringPiece path, std::unique_ptr<Value> in_value) {
783 DCHECK(IsStringUTF8(path));
786 StringPiece current_path(path);
787 Value* current_dictionary = this;
788 for (size_t delimiter_position = current_path.find('.');
789 delimiter_position != StringPiece::npos;
790 delimiter_position = current_path.find('.')) {
791 // Assume that we're indexing into a dictionary.
792 StringPiece key = current_path.substr(0, delimiter_position);
793 Value* child_dictionary =
794 current_dictionary->FindKeyOfType(key, Type::DICTIONARY);
795 if (!child_dictionary) {
797 current_dictionary->SetKey(key, Value(Type::DICTIONARY));
800 current_dictionary = child_dictionary;
801 current_path = current_path.substr(delimiter_position + 1);
804 return static_cast<DictionaryValue*>(current_dictionary)
805 ->SetWithoutPathExpansion(current_path, std::move(in_value));
808 Value* DictionaryValue::SetBoolean(StringPiece path, bool in_value) {
809 return Set(path, std::make_unique<Value>(in_value));
812 Value* DictionaryValue::SetInteger(StringPiece path, int in_value) {
813 return Set(path, std::make_unique<Value>(in_value));
816 Value* DictionaryValue::SetDouble(StringPiece path, double in_value) {
817 return Set(path, std::make_unique<Value>(in_value));
820 Value* DictionaryValue::SetString(StringPiece path, StringPiece in_value) {
821 return Set(path, std::make_unique<Value>(in_value));
824 Value* DictionaryValue::SetString(StringPiece path, const string16& in_value) {
825 return Set(path, std::make_unique<Value>(in_value));
828 DictionaryValue* DictionaryValue::SetDictionary(
830 std::unique_ptr<DictionaryValue> in_value) {
831 return static_cast<DictionaryValue*>(Set(path, std::move(in_value)));
834 ListValue* DictionaryValue::SetList(StringPiece path,
835 std::unique_ptr<ListValue> in_value) {
836 return static_cast<ListValue*>(Set(path, std::move(in_value)));
839 Value* DictionaryValue::SetWithoutPathExpansion(
841 std::unique_ptr<Value> in_value) {
842 // NOTE: We can't use |insert_or_assign| here, as only |try_emplace| does
843 // an explicit conversion from StringPiece to std::string if necessary.
844 auto result = dict_.try_emplace(key, std::move(in_value));
845 if (!result.second) {
846 // in_value is guaranteed to be still intact at this point.
847 result.first->second = std::move(in_value);
849 return result.first->second.get();
852 bool DictionaryValue::Get(StringPiece path,
853 const Value** out_value) const {
854 DCHECK(IsStringUTF8(path));
855 StringPiece current_path(path);
856 const DictionaryValue* current_dictionary = this;
857 for (size_t delimiter_position = current_path.find('.');
858 delimiter_position != std::string::npos;
859 delimiter_position = current_path.find('.')) {
860 const DictionaryValue* child_dictionary = nullptr;
861 if (!current_dictionary->GetDictionaryWithoutPathExpansion(
862 current_path.substr(0, delimiter_position), &child_dictionary)) {
866 current_dictionary = child_dictionary;
867 current_path = current_path.substr(delimiter_position + 1);
870 return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
873 bool DictionaryValue::Get(StringPiece path, Value** out_value) {
874 return static_cast<const DictionaryValue&>(*this).Get(
876 const_cast<const Value**>(out_value));
879 bool DictionaryValue::GetBoolean(StringPiece path, bool* bool_value) const {
881 if (!Get(path, &value))
884 return value->GetAsBoolean(bool_value);
887 bool DictionaryValue::GetInteger(StringPiece path, int* out_value) const {
889 if (!Get(path, &value))
892 return value->GetAsInteger(out_value);
895 bool DictionaryValue::GetDouble(StringPiece path, double* out_value) const {
897 if (!Get(path, &value))
900 return value->GetAsDouble(out_value);
903 bool DictionaryValue::GetString(StringPiece path,
904 std::string* out_value) const {
906 if (!Get(path, &value))
909 return value->GetAsString(out_value);
912 bool DictionaryValue::GetString(StringPiece path, string16* out_value) const {
914 if (!Get(path, &value))
917 return value->GetAsString(out_value);
920 bool DictionaryValue::GetStringASCII(StringPiece path,
921 std::string* out_value) const {
923 if (!GetString(path, &out))
926 if (!IsStringASCII(out)) {
931 out_value->assign(out);
935 bool DictionaryValue::GetBinary(StringPiece path,
936 const Value** out_value) const {
938 bool result = Get(path, &value);
939 if (!result || !value->is_blob())
948 bool DictionaryValue::GetBinary(StringPiece path, Value** out_value) {
949 return static_cast<const DictionaryValue&>(*this).GetBinary(
950 path, const_cast<const Value**>(out_value));
953 bool DictionaryValue::GetDictionary(StringPiece path,
954 const DictionaryValue** out_value) const {
956 bool result = Get(path, &value);
957 if (!result || !value->is_dict())
961 *out_value = static_cast<const DictionaryValue*>(value);
966 bool DictionaryValue::GetDictionary(StringPiece path,
967 DictionaryValue** out_value) {
968 return static_cast<const DictionaryValue&>(*this).GetDictionary(
970 const_cast<const DictionaryValue**>(out_value));
973 bool DictionaryValue::GetList(StringPiece path,
974 const ListValue** out_value) const {
976 bool result = Get(path, &value);
977 if (!result || !value->is_list())
981 *out_value = static_cast<const ListValue*>(value);
986 bool DictionaryValue::GetList(StringPiece path, ListValue** out_value) {
987 return static_cast<const DictionaryValue&>(*this).GetList(
989 const_cast<const ListValue**>(out_value));
992 bool DictionaryValue::GetWithoutPathExpansion(StringPiece key,
993 const Value** out_value) const {
994 DCHECK(IsStringUTF8(key));
995 auto entry_iterator = dict_.find(key);
996 if (entry_iterator == dict_.end())
1000 *out_value = entry_iterator->second.get();
1004 bool DictionaryValue::GetWithoutPathExpansion(StringPiece key,
1005 Value** out_value) {
1006 return static_cast<const DictionaryValue&>(*this).GetWithoutPathExpansion(
1008 const_cast<const Value**>(out_value));
1011 bool DictionaryValue::GetBooleanWithoutPathExpansion(StringPiece key,
1012 bool* out_value) const {
1014 if (!GetWithoutPathExpansion(key, &value))
1017 return value->GetAsBoolean(out_value);
1020 bool DictionaryValue::GetIntegerWithoutPathExpansion(StringPiece key,
1021 int* out_value) const {
1023 if (!GetWithoutPathExpansion(key, &value))
1026 return value->GetAsInteger(out_value);
1029 bool DictionaryValue::GetDoubleWithoutPathExpansion(StringPiece key,
1030 double* out_value) const {
1032 if (!GetWithoutPathExpansion(key, &value))
1035 return value->GetAsDouble(out_value);
1038 bool DictionaryValue::GetStringWithoutPathExpansion(
1040 std::string* out_value) const {
1042 if (!GetWithoutPathExpansion(key, &value))
1045 return value->GetAsString(out_value);
1048 bool DictionaryValue::GetStringWithoutPathExpansion(StringPiece key,
1049 string16* out_value) const {
1051 if (!GetWithoutPathExpansion(key, &value))
1054 return value->GetAsString(out_value);
1057 bool DictionaryValue::GetDictionaryWithoutPathExpansion(
1059 const DictionaryValue** out_value) const {
1061 bool result = GetWithoutPathExpansion(key, &value);
1062 if (!result || !value->is_dict())
1066 *out_value = static_cast<const DictionaryValue*>(value);
1071 bool DictionaryValue::GetDictionaryWithoutPathExpansion(
1073 DictionaryValue** out_value) {
1074 const DictionaryValue& const_this =
1075 static_cast<const DictionaryValue&>(*this);
1076 return const_this.GetDictionaryWithoutPathExpansion(
1078 const_cast<const DictionaryValue**>(out_value));
1081 bool DictionaryValue::GetListWithoutPathExpansion(
1083 const ListValue** out_value) const {
1085 bool result = GetWithoutPathExpansion(key, &value);
1086 if (!result || !value->is_list())
1090 *out_value = static_cast<const ListValue*>(value);
1095 bool DictionaryValue::GetListWithoutPathExpansion(StringPiece key,
1096 ListValue** out_value) {
1098 static_cast<const DictionaryValue&>(*this).GetListWithoutPathExpansion(
1100 const_cast<const ListValue**>(out_value));
1103 bool DictionaryValue::Remove(StringPiece path,
1104 std::unique_ptr<Value>* out_value) {
1105 DCHECK(IsStringUTF8(path));
1106 StringPiece current_path(path);
1107 DictionaryValue* current_dictionary = this;
1108 size_t delimiter_position = current_path.rfind('.');
1109 if (delimiter_position != StringPiece::npos) {
1110 if (!GetDictionary(current_path.substr(0, delimiter_position),
1111 ¤t_dictionary))
1113 current_path = current_path.substr(delimiter_position + 1);
1116 return current_dictionary->RemoveWithoutPathExpansion(current_path,
1120 bool DictionaryValue::RemoveWithoutPathExpansion(
1122 std::unique_ptr<Value>* out_value) {
1123 DCHECK(IsStringUTF8(key));
1124 auto entry_iterator = dict_.find(key);
1125 if (entry_iterator == dict_.end())
1129 *out_value = std::move(entry_iterator->second);
1130 dict_.erase(entry_iterator);
1134 bool DictionaryValue::RemovePath(StringPiece path,
1135 std::unique_ptr<Value>* out_value) {
1136 bool result = false;
1137 size_t delimiter_position = path.find('.');
1139 if (delimiter_position == std::string::npos)
1140 return RemoveWithoutPathExpansion(path, out_value);
1142 StringPiece subdict_path = path.substr(0, delimiter_position);
1143 DictionaryValue* subdict = nullptr;
1144 if (!GetDictionary(subdict_path, &subdict))
1146 result = subdict->RemovePath(path.substr(delimiter_position + 1),
1148 if (result && subdict->empty())
1149 RemoveWithoutPathExpansion(subdict_path, nullptr);
1154 std::unique_ptr<DictionaryValue> DictionaryValue::DeepCopyWithoutEmptyChildren()
1156 std::unique_ptr<DictionaryValue> copy =
1157 CopyDictionaryWithoutEmptyChildren(*this);
1159 copy = std::make_unique<DictionaryValue>();
1163 void DictionaryValue::Swap(DictionaryValue* other) {
1164 CHECK(other->is_dict());
1165 dict_.swap(other->dict_);
1168 DictionaryValue::Iterator::Iterator(const DictionaryValue& target)
1169 : target_(target), it_(target.dict_.begin()) {}
1171 DictionaryValue::Iterator::Iterator(const Iterator& other) = default;
1173 DictionaryValue::Iterator::~Iterator() = default;
1175 DictionaryValue* DictionaryValue::DeepCopy() const {
1176 return new DictionaryValue(dict_);
1179 std::unique_ptr<DictionaryValue> DictionaryValue::CreateDeepCopy() const {
1180 return std::make_unique<DictionaryValue>(dict_);
1183 ///////////////////// ListValue ////////////////////
1186 std::unique_ptr<ListValue> ListValue::From(std::unique_ptr<Value> value) {
1188 if (value && value->GetAsList(&out)) {
1189 ignore_result(value.release());
1190 return WrapUnique(out);
1195 ListValue::ListValue() : Value(Type::LIST) {}
1196 ListValue::ListValue(const ListStorage& in_list) : Value(in_list) {}
1197 ListValue::ListValue(ListStorage&& in_list) noexcept
1198 : Value(std::move(in_list)) {}
1200 void ListValue::Clear() {
1204 void ListValue::Reserve(size_t n) {
1208 bool ListValue::Set(size_t index, std::unique_ptr<Value> in_value) {
1212 if (index >= list_.size())
1213 list_.resize(index + 1);
1215 list_[index] = std::move(*in_value);
1219 bool ListValue::Get(size_t index, const Value** out_value) const {
1220 if (index >= list_.size())
1224 *out_value = &list_[index];
1229 bool ListValue::Get(size_t index, Value** out_value) {
1230 return static_cast<const ListValue&>(*this).Get(
1232 const_cast<const Value**>(out_value));
1235 bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
1237 if (!Get(index, &value))
1240 return value->GetAsBoolean(bool_value);
1243 bool ListValue::GetInteger(size_t index, int* out_value) const {
1245 if (!Get(index, &value))
1248 return value->GetAsInteger(out_value);
1251 bool ListValue::GetDouble(size_t index, double* out_value) const {
1253 if (!Get(index, &value))
1256 return value->GetAsDouble(out_value);
1259 bool ListValue::GetString(size_t index, std::string* out_value) const {
1261 if (!Get(index, &value))
1264 return value->GetAsString(out_value);
1267 bool ListValue::GetString(size_t index, string16* out_value) const {
1269 if (!Get(index, &value))
1272 return value->GetAsString(out_value);
1275 bool ListValue::GetDictionary(size_t index,
1276 const DictionaryValue** out_value) const {
1278 bool result = Get(index, &value);
1279 if (!result || !value->is_dict())
1283 *out_value = static_cast<const DictionaryValue*>(value);
1288 bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) {
1289 return static_cast<const ListValue&>(*this).GetDictionary(
1291 const_cast<const DictionaryValue**>(out_value));
1294 bool ListValue::GetList(size_t index, const ListValue** out_value) const {
1296 bool result = Get(index, &value);
1297 if (!result || !value->is_list())
1301 *out_value = static_cast<const ListValue*>(value);
1306 bool ListValue::GetList(size_t index, ListValue** out_value) {
1307 return static_cast<const ListValue&>(*this).GetList(
1309 const_cast<const ListValue**>(out_value));
1312 bool ListValue::Remove(size_t index, std::unique_ptr<Value>* out_value) {
1313 if (index >= list_.size())
1317 *out_value = std::make_unique<Value>(std::move(list_[index]));
1319 list_.erase(list_.begin() + index);
1323 bool ListValue::Remove(const Value& value, size_t* index) {
1324 auto it = std::find(list_.begin(), list_.end(), value);
1326 if (it == list_.end())
1330 *index = std::distance(list_.begin(), it);
1336 ListValue::iterator ListValue::Erase(iterator iter,
1337 std::unique_ptr<Value>* out_value) {
1339 *out_value = std::make_unique<Value>(std::move(*iter));
1341 return list_.erase(iter);
1344 void ListValue::Append(std::unique_ptr<Value> in_value) {
1345 list_.push_back(std::move(*in_value));
1348 void ListValue::AppendBoolean(bool in_value) {
1349 list_.emplace_back(in_value);
1352 void ListValue::AppendInteger(int in_value) {
1353 list_.emplace_back(in_value);
1356 void ListValue::AppendDouble(double in_value) {
1357 list_.emplace_back(in_value);
1360 void ListValue::AppendString(StringPiece in_value) {
1361 list_.emplace_back(in_value);
1364 void ListValue::AppendString(const string16& in_value) {
1365 list_.emplace_back(in_value);
1368 void ListValue::AppendStrings(const std::vector<std::string>& in_values) {
1369 list_.reserve(list_.size() + in_values.size());
1370 for (const auto& in_value : in_values)
1371 list_.emplace_back(in_value);
1374 void ListValue::AppendStrings(const std::vector<string16>& in_values) {
1375 list_.reserve(list_.size() + in_values.size());
1376 for (const auto& in_value : in_values)
1377 list_.emplace_back(in_value);
1380 bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) {
1382 if (ContainsValue(list_, *in_value))
1385 list_.push_back(std::move(*in_value));
1389 bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) {
1391 if (index > list_.size())
1394 list_.insert(list_.begin() + index, std::move(*in_value));
1398 ListValue::const_iterator ListValue::Find(const Value& value) const {
1399 return std::find(list_.begin(), list_.end(), value);
1402 void ListValue::Swap(ListValue* other) {
1403 CHECK(other->is_list());
1404 list_.swap(other->list_);
1407 ListValue* ListValue::DeepCopy() const {
1408 return new ListValue(list_);
1411 std::unique_ptr<ListValue> ListValue::CreateDeepCopy() const {
1412 return std::make_unique<ListValue>(list_);
1415 ValueSerializer::~ValueSerializer() = default;
1417 ValueDeserializer::~ValueDeserializer() = default;
1419 std::ostream& operator<<(std::ostream& out, const Value& value) {
1421 JSONWriter::WriteWithOptions(value, JSONWriter::OPTIONS_PRETTY_PRINT, &json);
1425 std::ostream& operator<<(std::ostream& out, const Value::Type& type) {
1426 if (static_cast<int>(type) < 0 ||
1427 static_cast<size_t>(type) >= base::size(kTypeNames))
1428 return out << "Invalid Type (index = " << static_cast<int>(type) << ")";
1429 return out << Value::GetTypeName(type);