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(arraysize(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());
80 std::unique_ptr<Value> Value::CreateWithCopiedBuffer(const char* buffer,
82 return std::make_unique<Value>(BlobStorage(buffer, buffer + size));
86 Value Value::FromUniquePtrValue(std::unique_ptr<Value> val) {
87 return std::move(*val);
91 std::unique_ptr<Value> Value::ToUniquePtrValue(Value val) {
92 return std::make_unique<Value>(std::move(val));
95 Value::Value(Value&& that) noexcept {
96 InternalMoveConstructFrom(std::move(that));
99 Value::Value() noexcept : type_(Type::NONE) {}
101 Value::Value(Type type) : type_(type) {
102 // Initialize with the default value.
117 new (&string_value_) std::string();
120 new (&binary_value_) BlobStorage();
122 case Type::DICTIONARY:
123 new (&dict_) DictStorage();
126 new (&list_) ListStorage();
131 Value::Value(bool in_bool) : type_(Type::BOOLEAN), bool_value_(in_bool) {}
133 Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {}
135 Value::Value(double in_double) : type_(Type::DOUBLE), double_value_(in_double) {
136 if (!std::isfinite(double_value_)) {
137 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
138 << "values cannot be represented in JSON";
143 Value::Value(const char* in_string) : Value(std::string(in_string)) {}
145 Value::Value(StringPiece in_string) : Value(std::string(in_string)) {}
147 Value::Value(std::string&& in_string) noexcept
148 : type_(Type::STRING), string_value_(std::move(in_string)) {
149 DCHECK(IsStringUTF8(string_value_));
152 Value::Value(const char16* in_string16) : Value(StringPiece16(in_string16)) {}
154 Value::Value(StringPiece16 in_string16) : Value(UTF16ToUTF8(in_string16)) {}
156 Value::Value(const BlobStorage& in_blob)
157 : type_(Type::BINARY), binary_value_(in_blob) {}
159 Value::Value(BlobStorage&& in_blob) noexcept
160 : type_(Type::BINARY), binary_value_(std::move(in_blob)) {}
162 Value::Value(const DictStorage& in_dict) : type_(Type::DICTIONARY), dict_() {
163 dict_.reserve(in_dict.size());
164 for (const auto& it : in_dict) {
165 dict_.try_emplace(dict_.end(), it.first,
166 std::make_unique<Value>(it.second->Clone()));
170 Value::Value(DictStorage&& in_dict) noexcept
171 : type_(Type::DICTIONARY), dict_(std::move(in_dict)) {}
173 Value::Value(const ListStorage& in_list) : type_(Type::LIST), list_() {
174 list_.reserve(in_list.size());
175 for (const auto& val : in_list)
176 list_.emplace_back(val.Clone());
179 Value::Value(ListStorage&& in_list) noexcept
180 : type_(Type::LIST), list_(std::move(in_list)) {}
182 Value& Value::operator=(Value&& that) noexcept {
184 InternalMoveConstructFrom(std::move(that));
189 Value Value::Clone() const {
194 return Value(bool_value_);
196 return Value(int_value_);
198 return Value(double_value_);
200 return Value(string_value_);
202 return Value(binary_value_);
203 case Type::DICTIONARY:
218 const char* Value::GetTypeName(Value::Type type) {
219 DCHECK_GE(static_cast<int>(type), 0);
220 DCHECK_LT(static_cast<size_t>(type), arraysize(kTypeNames));
221 return kTypeNames[static_cast<size_t>(type)];
224 bool Value::GetBool() const {
229 int Value::GetInt() const {
234 double Value::GetDouble() const {
236 return double_value_;
243 const std::string& Value::GetString() const {
245 return string_value_;
248 const Value::BlobStorage& Value::GetBlob() const {
250 return binary_value_;
253 Value::ListStorage& Value::GetList() {
258 const Value::ListStorage& Value::GetList() const {
263 Value* Value::FindKey(StringPiece key) {
264 return const_cast<Value*>(static_cast<const Value*>(this)->FindKey(key));
267 const Value* Value::FindKey(StringPiece key) const {
269 auto found = dict_.find(key);
270 if (found == dict_.end())
272 return found->second.get();
275 Value* Value::FindKeyOfType(StringPiece key, Type type) {
276 return const_cast<Value*>(
277 static_cast<const Value*>(this)->FindKeyOfType(key, type));
280 const Value* Value::FindKeyOfType(StringPiece key, Type type) const {
281 const Value* result = FindKey(key);
282 if (!result || result->type() != type)
287 bool Value::RemoveKey(StringPiece key) {
289 // NOTE: Can't directly return dict_->erase(key) due to MSVC warning C4800.
290 return dict_.erase(key) != 0;
293 Value* Value::SetKey(StringPiece key, Value value) {
295 // NOTE: We can't use |insert_or_assign| here, as only |try_emplace| does
296 // an explicit conversion from StringPiece to std::string if necessary.
297 auto val_ptr = std::make_unique<Value>(std::move(value));
298 auto result = dict_.try_emplace(key, std::move(val_ptr));
299 if (!result.second) {
300 // val_ptr is guaranteed to be still intact at this point.
301 result.first->second = std::move(val_ptr);
303 return result.first->second.get();
306 Value* Value::SetKey(std::string&& key, Value value) {
309 .insert_or_assign(std::move(key),
310 std::make_unique<Value>(std::move(value)))
311 .first->second.get();
314 Value* Value::SetKey(const char* key, Value value) {
315 return SetKey(StringPiece(key), std::move(value));
318 Value* Value::FindPath(std::initializer_list<StringPiece> path) {
319 return const_cast<Value*>(const_cast<const Value*>(this)->FindPath(path));
322 Value* Value::FindPath(span<const StringPiece> path) {
323 return const_cast<Value*>(const_cast<const Value*>(this)->FindPath(path));
326 const Value* Value::FindPath(std::initializer_list<StringPiece> path) const {
327 DCHECK_GE(path.size(), 2u) << "Use FindKey() for a path of length 1.";
328 return FindPath(make_span(path.begin(), path.size()));
331 const Value* Value::FindPath(span<const StringPiece> path) const {
332 const Value* cur = this;
333 for (const StringPiece component : path) {
334 if (!cur->is_dict() || (cur = cur->FindKey(component)) == nullptr)
340 Value* Value::FindPathOfType(std::initializer_list<StringPiece> path,
342 return const_cast<Value*>(
343 const_cast<const Value*>(this)->FindPathOfType(path, type));
346 Value* Value::FindPathOfType(span<const StringPiece> path, Type type) {
347 return const_cast<Value*>(
348 const_cast<const Value*>(this)->FindPathOfType(path, type));
351 const Value* Value::FindPathOfType(std::initializer_list<StringPiece> path,
353 DCHECK_GE(path.size(), 2u) << "Use FindKeyOfType() for a path of length 1.";
354 return FindPathOfType(make_span(path.begin(), path.size()), type);
357 const Value* Value::FindPathOfType(span<const StringPiece> path,
359 const Value* result = FindPath(path);
360 if (!result || result->type() != type)
365 Value* Value::SetPath(std::initializer_list<StringPiece> path, Value value) {
366 DCHECK_GE(path.size(), 2u) << "Use SetKey() for a path of length 1.";
367 return SetPath(make_span(path.begin(), path.size()), std::move(value));
370 Value* Value::SetPath(span<const StringPiece> path, Value value) {
371 DCHECK_NE(path.begin(), path.end()); // Can't be empty path.
373 // Walk/construct intermediate dictionaries. The last element requires
374 // special handling so skip it in this loop.
376 const StringPiece* cur_path = path.begin();
377 for (; (cur_path + 1) < path.end(); ++cur_path) {
381 // Use lower_bound to avoid doing the search twice for missing keys.
382 const StringPiece path_component = *cur_path;
383 auto found = cur->dict_.lower_bound(path_component);
384 if (found == cur->dict_.end() || found->first != path_component) {
385 // No key found, insert one.
386 auto inserted = cur->dict_.try_emplace(
387 found, path_component, std::make_unique<Value>(Type::DICTIONARY));
388 cur = inserted->second.get();
390 cur = found->second.get();
394 // "cur" will now contain the last dictionary to insert or replace into.
397 return cur->SetKey(*cur_path, std::move(value));
400 bool Value::RemovePath(std::initializer_list<StringPiece> path) {
401 DCHECK_GE(path.size(), 2u) << "Use RemoveKey() for a path of length 1.";
402 return RemovePath(make_span(path.begin(), path.size()));
405 bool Value::RemovePath(span<const StringPiece> path) {
406 if (!is_dict() || path.empty())
409 if (path.size() == 1)
410 return RemoveKey(path[0]);
412 auto found = dict_.find(path[0]);
413 if (found == dict_.end() || !found->second->is_dict())
416 bool removed = found->second->RemovePath(path.subspan(1));
417 if (removed && found->second->dict_.empty())
423 Value::dict_iterator_proxy Value::DictItems() {
425 return dict_iterator_proxy(&dict_);
428 Value::const_dict_iterator_proxy Value::DictItems() const {
430 return const_dict_iterator_proxy(&dict_);
433 size_t Value::DictSize() const {
438 bool Value::DictEmpty() const {
440 return dict_.empty();
443 bool Value::GetAsBoolean(bool* out_value) const {
444 if (out_value && is_bool()) {
445 *out_value = bool_value_;
451 bool Value::GetAsInteger(int* out_value) const {
452 if (out_value && is_int()) {
453 *out_value = int_value_;
459 bool Value::GetAsDouble(double* out_value) const {
460 if (out_value && is_double()) {
461 *out_value = double_value_;
463 } else if (out_value && is_int()) {
464 // Allow promotion from int to double.
465 *out_value = int_value_;
468 return is_double() || is_int();
471 bool Value::GetAsString(std::string* out_value) const {
472 if (out_value && is_string()) {
473 *out_value = string_value_;
479 bool Value::GetAsString(string16* out_value) const {
480 if (out_value && is_string()) {
481 *out_value = UTF8ToUTF16(string_value_);
487 bool Value::GetAsString(const Value** out_value) const {
488 if (out_value && is_string()) {
489 *out_value = static_cast<const Value*>(this);
495 bool Value::GetAsString(StringPiece* out_value) const {
496 if (out_value && is_string()) {
497 *out_value = string_value_;
503 bool Value::GetAsList(ListValue** out_value) {
504 if (out_value && is_list()) {
505 *out_value = static_cast<ListValue*>(this);
511 bool Value::GetAsList(const ListValue** out_value) const {
512 if (out_value && is_list()) {
513 *out_value = static_cast<const ListValue*>(this);
519 bool Value::GetAsDictionary(DictionaryValue** out_value) {
520 if (out_value && is_dict()) {
521 *out_value = static_cast<DictionaryValue*>(this);
527 bool Value::GetAsDictionary(const DictionaryValue** out_value) const {
528 if (out_value && is_dict()) {
529 *out_value = static_cast<const DictionaryValue*>(this);
535 Value* Value::DeepCopy() const {
536 return new Value(Clone());
539 std::unique_ptr<Value> Value::CreateDeepCopy() const {
540 return std::make_unique<Value>(Clone());
543 bool operator==(const Value& lhs, const Value& rhs) {
544 if (lhs.type_ != rhs.type_)
548 case Value::Type::NONE:
550 case Value::Type::BOOLEAN:
551 return lhs.bool_value_ == rhs.bool_value_;
552 case Value::Type::INTEGER:
553 return lhs.int_value_ == rhs.int_value_;
554 case Value::Type::DOUBLE:
555 return lhs.double_value_ == rhs.double_value_;
556 case Value::Type::STRING:
557 return lhs.string_value_ == rhs.string_value_;
558 case Value::Type::BINARY:
559 return lhs.binary_value_ == rhs.binary_value_;
560 // TODO(crbug.com/646113): Clean this up when DictionaryValue and ListValue
561 // are completely inlined.
562 case Value::Type::DICTIONARY:
563 if (lhs.dict_.size() != rhs.dict_.size())
565 return std::equal(std::begin(lhs.dict_), std::end(lhs.dict_),
566 std::begin(rhs.dict_),
567 [](const auto& u, const auto& v) {
568 return std::tie(u.first, *u.second) ==
569 std::tie(v.first, *v.second);
571 case Value::Type::LIST:
572 return lhs.list_ == rhs.list_;
579 bool operator!=(const Value& lhs, const Value& rhs) {
580 return !(lhs == rhs);
583 bool operator<(const Value& lhs, const Value& rhs) {
584 if (lhs.type_ != rhs.type_)
585 return lhs.type_ < rhs.type_;
588 case Value::Type::NONE:
590 case Value::Type::BOOLEAN:
591 return lhs.bool_value_ < rhs.bool_value_;
592 case Value::Type::INTEGER:
593 return lhs.int_value_ < rhs.int_value_;
594 case Value::Type::DOUBLE:
595 return lhs.double_value_ < rhs.double_value_;
596 case Value::Type::STRING:
597 return lhs.string_value_ < rhs.string_value_;
598 case Value::Type::BINARY:
599 return lhs.binary_value_ < rhs.binary_value_;
600 // TODO(crbug.com/646113): Clean this up when DictionaryValue and ListValue
601 // are completely inlined.
602 case Value::Type::DICTIONARY:
603 return std::lexicographical_compare(
604 std::begin(lhs.dict_), std::end(lhs.dict_), std::begin(rhs.dict_),
606 [](const Value::DictStorage::value_type& u,
607 const Value::DictStorage::value_type& v) {
608 return std::tie(u.first, *u.second) < std::tie(v.first, *v.second);
610 case Value::Type::LIST:
611 return lhs.list_ < rhs.list_;
618 bool operator>(const Value& lhs, const Value& rhs) {
622 bool operator<=(const Value& lhs, const Value& rhs) {
626 bool operator>=(const Value& lhs, const Value& rhs) {
630 bool Value::Equals(const Value* other) const {
632 return *this == *other;
635 size_t Value::EstimateMemoryUsage() const {
638 return base::trace_event::EstimateMemoryUsage(string_value_);
640 return base::trace_event::EstimateMemoryUsage(binary_value_);
641 case Type::DICTIONARY:
642 return base::trace_event::EstimateMemoryUsage(dict_);
644 return base::trace_event::EstimateMemoryUsage(list_);
650 void Value::InternalMoveConstructFrom(Value&& that) {
657 bool_value_ = that.bool_value_;
660 int_value_ = that.int_value_;
663 double_value_ = that.double_value_;
666 new (&string_value_) std::string(std::move(that.string_value_));
669 new (&binary_value_) BlobStorage(std::move(that.binary_value_));
671 case Type::DICTIONARY:
672 new (&dict_) DictStorage(std::move(that.dict_));
675 new (&list_) ListStorage(std::move(that.list_));
680 void Value::InternalCleanup() {
690 string_value_.~basic_string();
693 binary_value_.~BlobStorage();
695 case Type::DICTIONARY:
696 dict_.~DictStorage();
699 list_.~ListStorage();
704 ///////////////////// DictionaryValue ////////////////////
707 std::unique_ptr<DictionaryValue> DictionaryValue::From(
708 std::unique_ptr<Value> value) {
709 DictionaryValue* out;
710 if (value && value->GetAsDictionary(&out)) {
711 ignore_result(value.release());
712 return WrapUnique(out);
717 DictionaryValue::DictionaryValue() : Value(Type::DICTIONARY) {}
718 DictionaryValue::DictionaryValue(const DictStorage& in_dict) : Value(in_dict) {}
719 DictionaryValue::DictionaryValue(DictStorage&& in_dict) noexcept
720 : Value(std::move(in_dict)) {}
722 bool DictionaryValue::HasKey(StringPiece key) const {
723 DCHECK(IsStringUTF8(key));
724 auto current_entry = dict_.find(key);
725 DCHECK((current_entry == dict_.end()) || current_entry->second);
726 return current_entry != dict_.end();
729 void DictionaryValue::Clear() {
733 Value* DictionaryValue::Set(StringPiece path, std::unique_ptr<Value> in_value) {
734 DCHECK(IsStringUTF8(path));
737 StringPiece current_path(path);
738 Value* current_dictionary = this;
739 for (size_t delimiter_position = current_path.find('.');
740 delimiter_position != StringPiece::npos;
741 delimiter_position = current_path.find('.')) {
742 // Assume that we're indexing into a dictionary.
743 StringPiece key = current_path.substr(0, delimiter_position);
744 Value* child_dictionary =
745 current_dictionary->FindKeyOfType(key, Type::DICTIONARY);
746 if (!child_dictionary) {
748 current_dictionary->SetKey(key, Value(Type::DICTIONARY));
751 current_dictionary = child_dictionary;
752 current_path = current_path.substr(delimiter_position + 1);
755 return static_cast<DictionaryValue*>(current_dictionary)
756 ->SetWithoutPathExpansion(current_path, std::move(in_value));
759 Value* DictionaryValue::SetBoolean(StringPiece path, bool in_value) {
760 return Set(path, std::make_unique<Value>(in_value));
763 Value* DictionaryValue::SetInteger(StringPiece path, int in_value) {
764 return Set(path, std::make_unique<Value>(in_value));
767 Value* DictionaryValue::SetDouble(StringPiece path, double in_value) {
768 return Set(path, std::make_unique<Value>(in_value));
771 Value* DictionaryValue::SetString(StringPiece path, StringPiece in_value) {
772 return Set(path, std::make_unique<Value>(in_value));
775 Value* DictionaryValue::SetString(StringPiece path, const string16& in_value) {
776 return Set(path, std::make_unique<Value>(in_value));
779 DictionaryValue* DictionaryValue::SetDictionary(
781 std::unique_ptr<DictionaryValue> in_value) {
782 return static_cast<DictionaryValue*>(Set(path, std::move(in_value)));
785 ListValue* DictionaryValue::SetList(StringPiece path,
786 std::unique_ptr<ListValue> in_value) {
787 return static_cast<ListValue*>(Set(path, std::move(in_value)));
790 Value* DictionaryValue::SetWithoutPathExpansion(
792 std::unique_ptr<Value> in_value) {
793 // NOTE: We can't use |insert_or_assign| here, as only |try_emplace| does
794 // an explicit conversion from StringPiece to std::string if necessary.
795 auto result = dict_.try_emplace(key, std::move(in_value));
796 if (!result.second) {
797 // in_value is guaranteed to be still intact at this point.
798 result.first->second = std::move(in_value);
800 return result.first->second.get();
803 bool DictionaryValue::Get(StringPiece path,
804 const Value** out_value) const {
805 DCHECK(IsStringUTF8(path));
806 StringPiece current_path(path);
807 const DictionaryValue* current_dictionary = this;
808 for (size_t delimiter_position = current_path.find('.');
809 delimiter_position != std::string::npos;
810 delimiter_position = current_path.find('.')) {
811 const DictionaryValue* child_dictionary = nullptr;
812 if (!current_dictionary->GetDictionaryWithoutPathExpansion(
813 current_path.substr(0, delimiter_position), &child_dictionary)) {
817 current_dictionary = child_dictionary;
818 current_path = current_path.substr(delimiter_position + 1);
821 return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
824 bool DictionaryValue::Get(StringPiece path, Value** out_value) {
825 return static_cast<const DictionaryValue&>(*this).Get(
827 const_cast<const Value**>(out_value));
830 bool DictionaryValue::GetBoolean(StringPiece path, bool* bool_value) const {
832 if (!Get(path, &value))
835 return value->GetAsBoolean(bool_value);
838 bool DictionaryValue::GetInteger(StringPiece path, int* out_value) const {
840 if (!Get(path, &value))
843 return value->GetAsInteger(out_value);
846 bool DictionaryValue::GetDouble(StringPiece path, double* out_value) const {
848 if (!Get(path, &value))
851 return value->GetAsDouble(out_value);
854 bool DictionaryValue::GetString(StringPiece path,
855 std::string* out_value) const {
857 if (!Get(path, &value))
860 return value->GetAsString(out_value);
863 bool DictionaryValue::GetString(StringPiece path, string16* out_value) const {
865 if (!Get(path, &value))
868 return value->GetAsString(out_value);
871 bool DictionaryValue::GetStringASCII(StringPiece path,
872 std::string* out_value) const {
874 if (!GetString(path, &out))
877 if (!IsStringASCII(out)) {
882 out_value->assign(out);
886 bool DictionaryValue::GetBinary(StringPiece path,
887 const Value** out_value) const {
889 bool result = Get(path, &value);
890 if (!result || !value->is_blob())
899 bool DictionaryValue::GetBinary(StringPiece path, Value** out_value) {
900 return static_cast<const DictionaryValue&>(*this).GetBinary(
901 path, const_cast<const Value**>(out_value));
904 bool DictionaryValue::GetDictionary(StringPiece path,
905 const DictionaryValue** out_value) const {
907 bool result = Get(path, &value);
908 if (!result || !value->is_dict())
912 *out_value = static_cast<const DictionaryValue*>(value);
917 bool DictionaryValue::GetDictionary(StringPiece path,
918 DictionaryValue** out_value) {
919 return static_cast<const DictionaryValue&>(*this).GetDictionary(
921 const_cast<const DictionaryValue**>(out_value));
924 bool DictionaryValue::GetList(StringPiece path,
925 const ListValue** out_value) const {
927 bool result = Get(path, &value);
928 if (!result || !value->is_list())
932 *out_value = static_cast<const ListValue*>(value);
937 bool DictionaryValue::GetList(StringPiece path, ListValue** out_value) {
938 return static_cast<const DictionaryValue&>(*this).GetList(
940 const_cast<const ListValue**>(out_value));
943 bool DictionaryValue::GetWithoutPathExpansion(StringPiece key,
944 const Value** out_value) const {
945 DCHECK(IsStringUTF8(key));
946 auto entry_iterator = dict_.find(key);
947 if (entry_iterator == dict_.end())
951 *out_value = entry_iterator->second.get();
955 bool DictionaryValue::GetWithoutPathExpansion(StringPiece key,
957 return static_cast<const DictionaryValue&>(*this).GetWithoutPathExpansion(
959 const_cast<const Value**>(out_value));
962 bool DictionaryValue::GetBooleanWithoutPathExpansion(StringPiece key,
963 bool* out_value) const {
965 if (!GetWithoutPathExpansion(key, &value))
968 return value->GetAsBoolean(out_value);
971 bool DictionaryValue::GetIntegerWithoutPathExpansion(StringPiece key,
972 int* out_value) const {
974 if (!GetWithoutPathExpansion(key, &value))
977 return value->GetAsInteger(out_value);
980 bool DictionaryValue::GetDoubleWithoutPathExpansion(StringPiece key,
981 double* out_value) const {
983 if (!GetWithoutPathExpansion(key, &value))
986 return value->GetAsDouble(out_value);
989 bool DictionaryValue::GetStringWithoutPathExpansion(
991 std::string* out_value) const {
993 if (!GetWithoutPathExpansion(key, &value))
996 return value->GetAsString(out_value);
999 bool DictionaryValue::GetStringWithoutPathExpansion(StringPiece key,
1000 string16* out_value) const {
1002 if (!GetWithoutPathExpansion(key, &value))
1005 return value->GetAsString(out_value);
1008 bool DictionaryValue::GetDictionaryWithoutPathExpansion(
1010 const DictionaryValue** out_value) const {
1012 bool result = GetWithoutPathExpansion(key, &value);
1013 if (!result || !value->is_dict())
1017 *out_value = static_cast<const DictionaryValue*>(value);
1022 bool DictionaryValue::GetDictionaryWithoutPathExpansion(
1024 DictionaryValue** out_value) {
1025 const DictionaryValue& const_this =
1026 static_cast<const DictionaryValue&>(*this);
1027 return const_this.GetDictionaryWithoutPathExpansion(
1029 const_cast<const DictionaryValue**>(out_value));
1032 bool DictionaryValue::GetListWithoutPathExpansion(
1034 const ListValue** out_value) const {
1036 bool result = GetWithoutPathExpansion(key, &value);
1037 if (!result || !value->is_list())
1041 *out_value = static_cast<const ListValue*>(value);
1046 bool DictionaryValue::GetListWithoutPathExpansion(StringPiece key,
1047 ListValue** out_value) {
1049 static_cast<const DictionaryValue&>(*this).GetListWithoutPathExpansion(
1051 const_cast<const ListValue**>(out_value));
1054 bool DictionaryValue::Remove(StringPiece path,
1055 std::unique_ptr<Value>* out_value) {
1056 DCHECK(IsStringUTF8(path));
1057 StringPiece current_path(path);
1058 DictionaryValue* current_dictionary = this;
1059 size_t delimiter_position = current_path.rfind('.');
1060 if (delimiter_position != StringPiece::npos) {
1061 if (!GetDictionary(current_path.substr(0, delimiter_position),
1062 ¤t_dictionary))
1064 current_path = current_path.substr(delimiter_position + 1);
1067 return current_dictionary->RemoveWithoutPathExpansion(current_path,
1071 bool DictionaryValue::RemoveWithoutPathExpansion(
1073 std::unique_ptr<Value>* out_value) {
1074 DCHECK(IsStringUTF8(key));
1075 auto entry_iterator = dict_.find(key);
1076 if (entry_iterator == dict_.end())
1080 *out_value = std::move(entry_iterator->second);
1081 dict_.erase(entry_iterator);
1085 bool DictionaryValue::RemovePath(StringPiece path,
1086 std::unique_ptr<Value>* out_value) {
1087 bool result = false;
1088 size_t delimiter_position = path.find('.');
1090 if (delimiter_position == std::string::npos)
1091 return RemoveWithoutPathExpansion(path, out_value);
1093 StringPiece subdict_path = path.substr(0, delimiter_position);
1094 DictionaryValue* subdict = nullptr;
1095 if (!GetDictionary(subdict_path, &subdict))
1097 result = subdict->RemovePath(path.substr(delimiter_position + 1),
1099 if (result && subdict->empty())
1100 RemoveWithoutPathExpansion(subdict_path, nullptr);
1105 std::unique_ptr<DictionaryValue> DictionaryValue::DeepCopyWithoutEmptyChildren()
1107 std::unique_ptr<DictionaryValue> copy =
1108 CopyDictionaryWithoutEmptyChildren(*this);
1110 copy = std::make_unique<DictionaryValue>();
1114 void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
1115 CHECK(dictionary->is_dict());
1116 for (DictionaryValue::Iterator it(*dictionary); !it.IsAtEnd(); it.Advance()) {
1117 const Value* merge_value = &it.value();
1118 // Check whether we have to merge dictionaries.
1119 if (merge_value->is_dict()) {
1120 DictionaryValue* sub_dict;
1121 if (GetDictionaryWithoutPathExpansion(it.key(), &sub_dict)) {
1122 sub_dict->MergeDictionary(
1123 static_cast<const DictionaryValue*>(merge_value));
1127 // All other cases: Make a copy and hook it up.
1128 SetKey(it.key(), merge_value->Clone());
1132 void DictionaryValue::Swap(DictionaryValue* other) {
1133 CHECK(other->is_dict());
1134 dict_.swap(other->dict_);
1137 DictionaryValue::Iterator::Iterator(const DictionaryValue& target)
1138 : target_(target), it_(target.dict_.begin()) {}
1140 DictionaryValue::Iterator::Iterator(const Iterator& other) = default;
1142 DictionaryValue::Iterator::~Iterator() = default;
1144 DictionaryValue* DictionaryValue::DeepCopy() const {
1145 return new DictionaryValue(dict_);
1148 std::unique_ptr<DictionaryValue> DictionaryValue::CreateDeepCopy() const {
1149 return std::make_unique<DictionaryValue>(dict_);
1152 ///////////////////// ListValue ////////////////////
1155 std::unique_ptr<ListValue> ListValue::From(std::unique_ptr<Value> value) {
1157 if (value && value->GetAsList(&out)) {
1158 ignore_result(value.release());
1159 return WrapUnique(out);
1164 ListValue::ListValue() : Value(Type::LIST) {}
1165 ListValue::ListValue(const ListStorage& in_list) : Value(in_list) {}
1166 ListValue::ListValue(ListStorage&& in_list) noexcept
1167 : Value(std::move(in_list)) {}
1169 void ListValue::Clear() {
1173 void ListValue::Reserve(size_t n) {
1177 bool ListValue::Set(size_t index, std::unique_ptr<Value> in_value) {
1181 if (index >= list_.size())
1182 list_.resize(index + 1);
1184 list_[index] = std::move(*in_value);
1188 bool ListValue::Get(size_t index, const Value** out_value) const {
1189 if (index >= list_.size())
1193 *out_value = &list_[index];
1198 bool ListValue::Get(size_t index, Value** out_value) {
1199 return static_cast<const ListValue&>(*this).Get(
1201 const_cast<const Value**>(out_value));
1204 bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
1206 if (!Get(index, &value))
1209 return value->GetAsBoolean(bool_value);
1212 bool ListValue::GetInteger(size_t index, int* out_value) const {
1214 if (!Get(index, &value))
1217 return value->GetAsInteger(out_value);
1220 bool ListValue::GetDouble(size_t index, double* out_value) const {
1222 if (!Get(index, &value))
1225 return value->GetAsDouble(out_value);
1228 bool ListValue::GetString(size_t index, std::string* out_value) const {
1230 if (!Get(index, &value))
1233 return value->GetAsString(out_value);
1236 bool ListValue::GetString(size_t index, string16* out_value) const {
1238 if (!Get(index, &value))
1241 return value->GetAsString(out_value);
1244 bool ListValue::GetDictionary(size_t index,
1245 const DictionaryValue** out_value) const {
1247 bool result = Get(index, &value);
1248 if (!result || !value->is_dict())
1252 *out_value = static_cast<const DictionaryValue*>(value);
1257 bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) {
1258 return static_cast<const ListValue&>(*this).GetDictionary(
1260 const_cast<const DictionaryValue**>(out_value));
1263 bool ListValue::GetList(size_t index, const ListValue** out_value) const {
1265 bool result = Get(index, &value);
1266 if (!result || !value->is_list())
1270 *out_value = static_cast<const ListValue*>(value);
1275 bool ListValue::GetList(size_t index, ListValue** out_value) {
1276 return static_cast<const ListValue&>(*this).GetList(
1278 const_cast<const ListValue**>(out_value));
1281 bool ListValue::Remove(size_t index, std::unique_ptr<Value>* out_value) {
1282 if (index >= list_.size())
1286 *out_value = std::make_unique<Value>(std::move(list_[index]));
1288 list_.erase(list_.begin() + index);
1292 bool ListValue::Remove(const Value& value, size_t* index) {
1293 auto it = std::find(list_.begin(), list_.end(), value);
1295 if (it == list_.end())
1299 *index = std::distance(list_.begin(), it);
1305 ListValue::iterator ListValue::Erase(iterator iter,
1306 std::unique_ptr<Value>* out_value) {
1308 *out_value = std::make_unique<Value>(std::move(*iter));
1310 return list_.erase(iter);
1313 void ListValue::Append(std::unique_ptr<Value> in_value) {
1314 list_.push_back(std::move(*in_value));
1317 void ListValue::AppendBoolean(bool in_value) {
1318 list_.emplace_back(in_value);
1321 void ListValue::AppendInteger(int in_value) {
1322 list_.emplace_back(in_value);
1325 void ListValue::AppendDouble(double in_value) {
1326 list_.emplace_back(in_value);
1329 void ListValue::AppendString(StringPiece in_value) {
1330 list_.emplace_back(in_value);
1333 void ListValue::AppendString(const string16& in_value) {
1334 list_.emplace_back(in_value);
1337 void ListValue::AppendStrings(const std::vector<std::string>& in_values) {
1338 list_.reserve(list_.size() + in_values.size());
1339 for (const auto& in_value : in_values)
1340 list_.emplace_back(in_value);
1343 void ListValue::AppendStrings(const std::vector<string16>& in_values) {
1344 list_.reserve(list_.size() + in_values.size());
1345 for (const auto& in_value : in_values)
1346 list_.emplace_back(in_value);
1349 bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) {
1351 if (ContainsValue(list_, *in_value))
1354 list_.push_back(std::move(*in_value));
1358 bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) {
1360 if (index > list_.size())
1363 list_.insert(list_.begin() + index, std::move(*in_value));
1367 ListValue::const_iterator ListValue::Find(const Value& value) const {
1368 return std::find(list_.begin(), list_.end(), value);
1371 void ListValue::Swap(ListValue* other) {
1372 CHECK(other->is_list());
1373 list_.swap(other->list_);
1376 ListValue* ListValue::DeepCopy() const {
1377 return new ListValue(list_);
1380 std::unique_ptr<ListValue> ListValue::CreateDeepCopy() const {
1381 return std::make_unique<ListValue>(list_);
1384 ValueSerializer::~ValueSerializer() = default;
1386 ValueDeserializer::~ValueDeserializer() = default;
1388 std::ostream& operator<<(std::ostream& out, const Value& value) {
1390 JSONWriter::WriteWithOptions(value, JSONWriter::OPTIONS_PRETTY_PRINT, &json);
1394 std::ostream& operator<<(std::ostream& out, const Value::Type& type) {
1395 if (static_cast<int>(type) < 0 ||
1396 static_cast<size_t>(type) >= arraysize(kTypeNames))
1397 return out << "Invalid Type (index = " << static_cast<int>(type) << ")";
1398 return out << Value::GetTypeName(type);