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. 4 5 #include "base/values.h" 6 7 #include <string.h> 8 9 #include <algorithm> 10 #include <cmath> 11 #include <new> 12 #include <ostream> 13 #include <utility> 14 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 // Unsupported in libchrome 22 // #include "base/trace_event/memory_usage_estimator.h" 23 24 namespace base { 25 26 namespace { 27 28 const char* const kTypeNames[] = {"null", "boolean", "integer", "double", 29 "string", "binary", "dictionary", "list"}; 30 static_assert(arraysize(kTypeNames) == 31 static_cast<size_t>(Value::Type::LIST) + 1, 32 "kTypeNames Has Wrong Size"); 33 34 std::unique_ptr<Value> CopyWithoutEmptyChildren(const Value& node); 35 36 // Make a deep copy of |node|, but don't include empty lists or dictionaries 37 // in the copy. It's possible for this function to return NULL and it 38 // expects |node| to always be non-NULL. 39 std::unique_ptr<Value> CopyListWithoutEmptyChildren(const Value& list) { 40 Value copy(Value::Type::LIST); 41 for (const auto& entry : list.GetList()) { 42 std::unique_ptr<Value> child_copy = CopyWithoutEmptyChildren(entry); 43 if (child_copy) 44 copy.GetList().push_back(std::move(*child_copy)); 45 } 46 return copy.GetList().empty() ? nullptr 47 : std::make_unique<Value>(std::move(copy)); 48 } 49 50 std::unique_ptr<DictionaryValue> CopyDictionaryWithoutEmptyChildren( 51 const DictionaryValue& dict) { 52 std::unique_ptr<DictionaryValue> copy; 53 for (DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { 54 std::unique_ptr<Value> child_copy = CopyWithoutEmptyChildren(it.value()); 55 if (child_copy) { 56 if (!copy) 57 copy = std::make_unique<DictionaryValue>(); 58 copy->SetWithoutPathExpansion(it.key(), std::move(child_copy)); 59 } 60 } 61 return copy; 62 } 63 64 std::unique_ptr<Value> CopyWithoutEmptyChildren(const Value& node) { 65 switch (node.type()) { 66 case Value::Type::LIST: 67 return CopyListWithoutEmptyChildren(static_cast<const ListValue&>(node)); 68 69 case Value::Type::DICTIONARY: 70 return CopyDictionaryWithoutEmptyChildren( 71 static_cast<const DictionaryValue&>(node)); 72 73 default: 74 return std::make_unique<Value>(node.Clone()); 75 } 76 } 77 78 } // namespace 79 80 // static 81 std::unique_ptr<Value> Value::CreateWithCopiedBuffer(const char* buffer, 82 size_t size) { 83 return std::make_unique<Value>(BlobStorage(buffer, buffer + size)); 84 } 85 86 // static 87 Value Value::FromUniquePtrValue(std::unique_ptr<Value> val) { 88 return std::move(*val); 89 } 90 91 // static 92 std::unique_ptr<Value> Value::ToUniquePtrValue(Value val) { 93 return std::make_unique<Value>(std::move(val)); 94 } 95 96 Value::Value(Value&& that) noexcept { 97 InternalMoveConstructFrom(std::move(that)); 98 } 99 100 Value::Value() noexcept : type_(Type::NONE) {} 101 102 Value::Value(Type type) : type_(type) { 103 // Initialize with the default value. 104 switch (type_) { 105 case Type::NONE: 106 return; 107 108 case Type::BOOLEAN: 109 bool_value_ = false; 110 return; 111 case Type::INTEGER: 112 int_value_ = 0; 113 return; 114 case Type::DOUBLE: 115 double_value_ = 0.0; 116 return; 117 case Type::STRING: 118 new (&string_value_) std::string(); 119 return; 120 case Type::BINARY: 121 new (&binary_value_) BlobStorage(); 122 return; 123 case Type::DICTIONARY: 124 new (&dict_) DictStorage(); 125 return; 126 case Type::LIST: 127 new (&list_) ListStorage(); 128 return; 129 } 130 } 131 132 Value::Value(bool in_bool) : type_(Type::BOOLEAN), bool_value_(in_bool) {} 133 134 Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {} 135 136 Value::Value(double in_double) : type_(Type::DOUBLE), double_value_(in_double) { 137 if (!std::isfinite(double_value_)) { 138 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) " 139 << "values cannot be represented in JSON"; 140 double_value_ = 0.0; 141 } 142 } 143 144 Value::Value(const char* in_string) : Value(std::string(in_string)) {} 145 146 Value::Value(StringPiece in_string) : Value(std::string(in_string)) {} 147 148 Value::Value(std::string&& in_string) noexcept 149 : type_(Type::STRING), string_value_(std::move(in_string)) { 150 DCHECK(IsStringUTF8(string_value_)); 151 } 152 153 Value::Value(const char16* in_string16) : Value(StringPiece16(in_string16)) {} 154 155 Value::Value(StringPiece16 in_string16) : Value(UTF16ToUTF8(in_string16)) {} 156 157 Value::Value(const BlobStorage& in_blob) 158 : type_(Type::BINARY), binary_value_(in_blob) {} 159 160 Value::Value(BlobStorage&& in_blob) noexcept 161 : type_(Type::BINARY), binary_value_(std::move(in_blob)) {} 162 163 Value::Value(const DictStorage& in_dict) : type_(Type::DICTIONARY), dict_() { 164 dict_.reserve(in_dict.size()); 165 for (const auto& it : in_dict) { 166 dict_.try_emplace(dict_.end(), it.first, 167 std::make_unique<Value>(it.second->Clone())); 168 } 169 } 170 171 Value::Value(DictStorage&& in_dict) noexcept 172 : type_(Type::DICTIONARY), dict_(std::move(in_dict)) {} 173 174 Value::Value(const ListStorage& in_list) : type_(Type::LIST), list_() { 175 list_.reserve(in_list.size()); 176 for (const auto& val : in_list) 177 list_.emplace_back(val.Clone()); 178 } 179 180 Value::Value(ListStorage&& in_list) noexcept 181 : type_(Type::LIST), list_(std::move(in_list)) {} 182 183 Value& Value::operator=(Value&& that) noexcept { 184 InternalCleanup(); 185 InternalMoveConstructFrom(std::move(that)); 186 187 return *this; 188 } 189 190 Value Value::Clone() const { 191 switch (type_) { 192 case Type::NONE: 193 return Value(); 194 case Type::BOOLEAN: 195 return Value(bool_value_); 196 case Type::INTEGER: 197 return Value(int_value_); 198 case Type::DOUBLE: 199 return Value(double_value_); 200 case Type::STRING: 201 return Value(string_value_); 202 case Type::BINARY: 203 return Value(binary_value_); 204 case Type::DICTIONARY: 205 return Value(dict_); 206 case Type::LIST: 207 return Value(list_); 208 } 209 210 NOTREACHED(); 211 return Value(); 212 } 213 214 Value::~Value() { 215 InternalCleanup(); 216 } 217 218 // static 219 const char* Value::GetTypeName(Value::Type type) { 220 DCHECK_GE(static_cast<int>(type), 0); 221 DCHECK_LT(static_cast<size_t>(type), arraysize(kTypeNames)); 222 return kTypeNames[static_cast<size_t>(type)]; 223 } 224 225 bool Value::GetBool() const { 226 CHECK(is_bool()); 227 return bool_value_; 228 } 229 230 int Value::GetInt() const { 231 CHECK(is_int()); 232 return int_value_; 233 } 234 235 double Value::GetDouble() const { 236 if (is_double()) 237 return double_value_; 238 if (is_int()) 239 return int_value_; 240 CHECK(false); 241 return 0.0; 242 } 243 244 const std::string& Value::GetString() const { 245 CHECK(is_string()); 246 return string_value_; 247 } 248 249 const Value::BlobStorage& Value::GetBlob() const { 250 CHECK(is_blob()); 251 return binary_value_; 252 } 253 254 Value::ListStorage& Value::GetList() { 255 CHECK(is_list()); 256 return list_; 257 } 258 259 const Value::ListStorage& Value::GetList() const { 260 CHECK(is_list()); 261 return list_; 262 } 263 264 Value* Value::FindKey(StringPiece key) { 265 return const_cast<Value*>(static_cast<const Value*>(this)->FindKey(key)); 266 } 267 268 const Value* Value::FindKey(StringPiece key) const { 269 CHECK(is_dict()); 270 auto found = dict_.find(key); 271 if (found == dict_.end()) 272 return nullptr; 273 return found->second.get(); 274 } 275 276 Value* Value::FindKeyOfType(StringPiece key, Type type) { 277 return const_cast<Value*>( 278 static_cast<const Value*>(this)->FindKeyOfType(key, type)); 279 } 280 281 const Value* Value::FindKeyOfType(StringPiece key, Type type) const { 282 const Value* result = FindKey(key); 283 if (!result || result->type() != type) 284 return nullptr; 285 return result; 286 } 287 288 bool Value::RemoveKey(StringPiece key) { 289 CHECK(is_dict()); 290 // NOTE: Can't directly return dict_->erase(key) due to MSVC warning C4800. 291 return dict_.erase(key) != 0; 292 } 293 294 Value* Value::SetKey(StringPiece key, Value value) { 295 CHECK(is_dict()); 296 // NOTE: We can't use |insert_or_assign| here, as only |try_emplace| does 297 // an explicit conversion from StringPiece to std::string if necessary. 298 auto val_ptr = std::make_unique<Value>(std::move(value)); 299 auto result = dict_.try_emplace(key, std::move(val_ptr)); 300 if (!result.second) { 301 // val_ptr is guaranteed to be still intact at this point. 302 result.first->second = std::move(val_ptr); 303 } 304 return result.first->second.get(); 305 } 306 307 Value* Value::SetKey(std::string&& key, Value value) { 308 CHECK(is_dict()); 309 return dict_ 310 .insert_or_assign(std::move(key), 311 std::make_unique<Value>(std::move(value))) 312 .first->second.get(); 313 } 314 315 Value* Value::SetKey(const char* key, Value value) { 316 return SetKey(StringPiece(key), std::move(value)); 317 } 318 319 Value* Value::FindPath(std::initializer_list<StringPiece> path) { 320 return const_cast<Value*>(const_cast<const Value*>(this)->FindPath(path)); 321 } 322 323 Value* Value::FindPath(span<const StringPiece> path) { 324 return const_cast<Value*>(const_cast<const Value*>(this)->FindPath(path)); 325 } 326 327 const Value* Value::FindPath(std::initializer_list<StringPiece> path) const { 328 DCHECK_GE(path.size(), 2u) << "Use FindKey() for a path of length 1."; 329 return FindPath(make_span(path.begin(), path.size())); 330 } 331 332 const Value* Value::FindPath(span<const StringPiece> path) const { 333 const Value* cur = this; 334 for (const StringPiece component : path) { 335 if (!cur->is_dict() || (cur = cur->FindKey(component)) == nullptr) 336 return nullptr; 337 } 338 return cur; 339 } 340 341 Value* Value::FindPathOfType(std::initializer_list<StringPiece> path, 342 Type type) { 343 return const_cast<Value*>( 344 const_cast<const Value*>(this)->FindPathOfType(path, type)); 345 } 346 347 Value* Value::FindPathOfType(span<const StringPiece> path, Type type) { 348 return const_cast<Value*>( 349 const_cast<const Value*>(this)->FindPathOfType(path, type)); 350 } 351 352 const Value* Value::FindPathOfType(std::initializer_list<StringPiece> path, 353 Type type) const { 354 DCHECK_GE(path.size(), 2u) << "Use FindKeyOfType() for a path of length 1."; 355 return FindPathOfType(make_span(path.begin(), path.size()), type); 356 } 357 358 const Value* Value::FindPathOfType(span<const StringPiece> path, 359 Type type) const { 360 const Value* result = FindPath(path); 361 if (!result || result->type() != type) 362 return nullptr; 363 return result; 364 } 365 366 Value* Value::SetPath(std::initializer_list<StringPiece> path, Value value) { 367 DCHECK_GE(path.size(), 2u) << "Use SetKey() for a path of length 1."; 368 return SetPath(make_span(path.begin(), path.size()), std::move(value)); 369 } 370 371 Value* Value::SetPath(span<const StringPiece> path, Value value) { 372 DCHECK_NE(path.begin(), path.end()); // Can't be empty path. 373 374 // Walk/construct intermediate dictionaries. The last element requires 375 // special handling so skip it in this loop. 376 Value* cur = this; 377 const StringPiece* cur_path = path.begin(); 378 for (; (cur_path + 1) < path.end(); ++cur_path) { 379 if (!cur->is_dict()) 380 return nullptr; 381 382 // Use lower_bound to avoid doing the search twice for missing keys. 383 const StringPiece path_component = *cur_path; 384 auto found = cur->dict_.lower_bound(path_component); 385 if (found == cur->dict_.end() || found->first != path_component) { 386 // No key found, insert one. 387 auto inserted = cur->dict_.try_emplace( 388 found, path_component, std::make_unique<Value>(Type::DICTIONARY)); 389 cur = inserted->second.get(); 390 } else { 391 cur = found->second.get(); 392 } 393 } 394 395 // "cur" will now contain the last dictionary to insert or replace into. 396 if (!cur->is_dict()) 397 return nullptr; 398 return cur->SetKey(*cur_path, std::move(value)); 399 } 400 401 bool Value::RemovePath(std::initializer_list<StringPiece> path) { 402 DCHECK_GE(path.size(), 2u) << "Use RemoveKey() for a path of length 1."; 403 return RemovePath(make_span(path.begin(), path.size())); 404 } 405 406 bool Value::RemovePath(span<const StringPiece> path) { 407 if (!is_dict() || path.empty()) 408 return false; 409 410 if (path.size() == 1) 411 return RemoveKey(path[0]); 412 413 auto found = dict_.find(path[0]); 414 if (found == dict_.end() || !found->second->is_dict()) 415 return false; 416 417 bool removed = found->second->RemovePath(path.subspan(1)); 418 if (removed && found->second->dict_.empty()) 419 dict_.erase(found); 420 421 return removed; 422 } 423 424 Value::dict_iterator_proxy Value::DictItems() { 425 CHECK(is_dict()); 426 return dict_iterator_proxy(&dict_); 427 } 428 429 Value::const_dict_iterator_proxy Value::DictItems() const { 430 CHECK(is_dict()); 431 return const_dict_iterator_proxy(&dict_); 432 } 433 434 size_t Value::DictSize() const { 435 CHECK(is_dict()); 436 return dict_.size(); 437 } 438 439 bool Value::DictEmpty() const { 440 CHECK(is_dict()); 441 return dict_.empty(); 442 } 443 444 bool Value::GetAsBoolean(bool* out_value) const { 445 if (out_value && is_bool()) { 446 *out_value = bool_value_; 447 return true; 448 } 449 return is_bool(); 450 } 451 452 bool Value::GetAsInteger(int* out_value) const { 453 if (out_value && is_int()) { 454 *out_value = int_value_; 455 return true; 456 } 457 return is_int(); 458 } 459 460 bool Value::GetAsDouble(double* out_value) const { 461 if (out_value && is_double()) { 462 *out_value = double_value_; 463 return true; 464 } else if (out_value && is_int()) { 465 // Allow promotion from int to double. 466 *out_value = int_value_; 467 return true; 468 } 469 return is_double() || is_int(); 470 } 471 472 bool Value::GetAsString(std::string* out_value) const { 473 if (out_value && is_string()) { 474 *out_value = string_value_; 475 return true; 476 } 477 return is_string(); 478 } 479 480 bool Value::GetAsString(string16* out_value) const { 481 if (out_value && is_string()) { 482 *out_value = UTF8ToUTF16(string_value_); 483 return true; 484 } 485 return is_string(); 486 } 487 488 bool Value::GetAsString(const Value** out_value) const { 489 if (out_value && is_string()) { 490 *out_value = static_cast<const Value*>(this); 491 return true; 492 } 493 return is_string(); 494 } 495 496 bool Value::GetAsString(StringPiece* out_value) const { 497 if (out_value && is_string()) { 498 *out_value = string_value_; 499 return true; 500 } 501 return is_string(); 502 } 503 504 bool Value::GetAsList(ListValue** out_value) { 505 if (out_value && is_list()) { 506 *out_value = static_cast<ListValue*>(this); 507 return true; 508 } 509 return is_list(); 510 } 511 512 bool Value::GetAsList(const ListValue** out_value) const { 513 if (out_value && is_list()) { 514 *out_value = static_cast<const ListValue*>(this); 515 return true; 516 } 517 return is_list(); 518 } 519 520 bool Value::GetAsDictionary(DictionaryValue** out_value) { 521 if (out_value && is_dict()) { 522 *out_value = static_cast<DictionaryValue*>(this); 523 return true; 524 } 525 return is_dict(); 526 } 527 528 bool Value::GetAsDictionary(const DictionaryValue** out_value) const { 529 if (out_value && is_dict()) { 530 *out_value = static_cast<const DictionaryValue*>(this); 531 return true; 532 } 533 return is_dict(); 534 } 535 536 Value* Value::DeepCopy() const { 537 return new Value(Clone()); 538 } 539 540 std::unique_ptr<Value> Value::CreateDeepCopy() const { 541 return std::make_unique<Value>(Clone()); 542 } 543 544 bool operator==(const Value& lhs, const Value& rhs) { 545 if (lhs.type_ != rhs.type_) 546 return false; 547 548 switch (lhs.type_) { 549 case Value::Type::NONE: 550 return true; 551 case Value::Type::BOOLEAN: 552 return lhs.bool_value_ == rhs.bool_value_; 553 case Value::Type::INTEGER: 554 return lhs.int_value_ == rhs.int_value_; 555 case Value::Type::DOUBLE: 556 return lhs.double_value_ == rhs.double_value_; 557 case Value::Type::STRING: 558 return lhs.string_value_ == rhs.string_value_; 559 case Value::Type::BINARY: 560 return lhs.binary_value_ == rhs.binary_value_; 561 // TODO(crbug.com/646113): Clean this up when DictionaryValue and ListValue 562 // are completely inlined. 563 case Value::Type::DICTIONARY: 564 if (lhs.dict_.size() != rhs.dict_.size()) 565 return false; 566 return std::equal(std::begin(lhs.dict_), std::end(lhs.dict_), 567 std::begin(rhs.dict_), 568 [](const auto& u, const auto& v) { 569 return std::tie(u.first, *u.second) == 570 std::tie(v.first, *v.second); 571 }); 572 case Value::Type::LIST: 573 return lhs.list_ == rhs.list_; 574 } 575 576 NOTREACHED(); 577 return false; 578 } 579 580 bool operator!=(const Value& lhs, const Value& rhs) { 581 return !(lhs == rhs); 582 } 583 584 bool operator<(const Value& lhs, const Value& rhs) { 585 if (lhs.type_ != rhs.type_) 586 return lhs.type_ < rhs.type_; 587 588 switch (lhs.type_) { 589 case Value::Type::NONE: 590 return false; 591 case Value::Type::BOOLEAN: 592 return lhs.bool_value_ < rhs.bool_value_; 593 case Value::Type::INTEGER: 594 return lhs.int_value_ < rhs.int_value_; 595 case Value::Type::DOUBLE: 596 return lhs.double_value_ < rhs.double_value_; 597 case Value::Type::STRING: 598 return lhs.string_value_ < rhs.string_value_; 599 case Value::Type::BINARY: 600 return lhs.binary_value_ < rhs.binary_value_; 601 // TODO(crbug.com/646113): Clean this up when DictionaryValue and ListValue 602 // are completely inlined. 603 case Value::Type::DICTIONARY: 604 return std::lexicographical_compare( 605 std::begin(lhs.dict_), std::end(lhs.dict_), std::begin(rhs.dict_), 606 std::end(rhs.dict_), 607 [](const Value::DictStorage::value_type& u, 608 const Value::DictStorage::value_type& v) { 609 return std::tie(u.first, *u.second) < std::tie(v.first, *v.second); 610 }); 611 case Value::Type::LIST: 612 return lhs.list_ < rhs.list_; 613 } 614 615 NOTREACHED(); 616 return false; 617 } 618 619 bool operator>(const Value& lhs, const Value& rhs) { 620 return rhs < lhs; 621 } 622 623 bool operator<=(const Value& lhs, const Value& rhs) { 624 return !(rhs < lhs); 625 } 626 627 bool operator>=(const Value& lhs, const Value& rhs) { 628 return !(lhs < rhs); 629 } 630 631 bool Value::Equals(const Value* other) const { 632 DCHECK(other); 633 return *this == *other; 634 } 635 636 // Unsupported in libchrome 637 // size_t Value::EstimateMemoryUsage() const { 638 // switch (type_) { 639 // case Type::STRING: 640 // return base::trace_event::EstimateMemoryUsage(string_value_); 641 // case Type::BINARY: 642 // return base::trace_event::EstimateMemoryUsage(binary_value_); 643 // case Type::DICTIONARY: 644 // return base::trace_event::EstimateMemoryUsage(dict_); 645 // case Type::LIST: 646 // return base::trace_event::EstimateMemoryUsage(list_); 647 // default: 648 // return 0; 649 // } 650 // } 651 652 void Value::InternalMoveConstructFrom(Value&& that) { 653 type_ = that.type_; 654 655 switch (type_) { 656 case Type::NONE: 657 return; 658 case Type::BOOLEAN: 659 bool_value_ = that.bool_value_; 660 return; 661 case Type::INTEGER: 662 int_value_ = that.int_value_; 663 return; 664 case Type::DOUBLE: 665 double_value_ = that.double_value_; 666 return; 667 case Type::STRING: 668 new (&string_value_) std::string(std::move(that.string_value_)); 669 return; 670 case Type::BINARY: 671 new (&binary_value_) BlobStorage(std::move(that.binary_value_)); 672 return; 673 case Type::DICTIONARY: 674 new (&dict_) DictStorage(std::move(that.dict_)); 675 return; 676 case Type::LIST: 677 new (&list_) ListStorage(std::move(that.list_)); 678 return; 679 } 680 } 681 682 void Value::InternalCleanup() { 683 switch (type_) { 684 case Type::NONE: 685 case Type::BOOLEAN: 686 case Type::INTEGER: 687 case Type::DOUBLE: 688 // Nothing to do 689 return; 690 691 case Type::STRING: 692 string_value_.~basic_string(); 693 return; 694 case Type::BINARY: 695 binary_value_.~BlobStorage(); 696 return; 697 case Type::DICTIONARY: 698 dict_.~DictStorage(); 699 return; 700 case Type::LIST: 701 list_.~ListStorage(); 702 return; 703 } 704 } 705 706 ///////////////////// DictionaryValue //////////////////// 707 708 // static 709 std::unique_ptr<DictionaryValue> DictionaryValue::From( 710 std::unique_ptr<Value> value) { 711 DictionaryValue* out; 712 if (value && value->GetAsDictionary(&out)) { 713 ignore_result(value.release()); 714 return WrapUnique(out); 715 } 716 return nullptr; 717 } 718 719 DictionaryValue::DictionaryValue() : Value(Type::DICTIONARY) {} 720 DictionaryValue::DictionaryValue(const DictStorage& in_dict) : Value(in_dict) {} 721 DictionaryValue::DictionaryValue(DictStorage&& in_dict) noexcept 722 : Value(std::move(in_dict)) {} 723 724 bool DictionaryValue::HasKey(StringPiece key) const { 725 DCHECK(IsStringUTF8(key)); 726 auto current_entry = dict_.find(key); 727 DCHECK((current_entry == dict_.end()) || current_entry->second); 728 return current_entry != dict_.end(); 729 } 730 731 void DictionaryValue::Clear() { 732 dict_.clear(); 733 } 734 735 Value* DictionaryValue::Set(StringPiece path, std::unique_ptr<Value> in_value) { 736 DCHECK(IsStringUTF8(path)); 737 DCHECK(in_value); 738 739 StringPiece current_path(path); 740 Value* current_dictionary = this; 741 for (size_t delimiter_position = current_path.find('.'); 742 delimiter_position != StringPiece::npos; 743 delimiter_position = current_path.find('.')) { 744 // Assume that we're indexing into a dictionary. 745 StringPiece key = current_path.substr(0, delimiter_position); 746 Value* child_dictionary = 747 current_dictionary->FindKeyOfType(key, Type::DICTIONARY); 748 if (!child_dictionary) { 749 child_dictionary = 750 current_dictionary->SetKey(key, Value(Type::DICTIONARY)); 751 } 752 753 current_dictionary = child_dictionary; 754 current_path = current_path.substr(delimiter_position + 1); 755 } 756 757 return static_cast<DictionaryValue*>(current_dictionary) 758 ->SetWithoutPathExpansion(current_path, std::move(in_value)); 759 } 760 761 Value* DictionaryValue::SetBoolean(StringPiece path, bool in_value) { 762 return Set(path, std::make_unique<Value>(in_value)); 763 } 764 765 Value* DictionaryValue::SetInteger(StringPiece path, int in_value) { 766 return Set(path, std::make_unique<Value>(in_value)); 767 } 768 769 Value* DictionaryValue::SetDouble(StringPiece path, double in_value) { 770 return Set(path, std::make_unique<Value>(in_value)); 771 } 772 773 Value* DictionaryValue::SetString(StringPiece path, StringPiece in_value) { 774 return Set(path, std::make_unique<Value>(in_value)); 775 } 776 777 Value* DictionaryValue::SetString(StringPiece path, const string16& in_value) { 778 return Set(path, std::make_unique<Value>(in_value)); 779 } 780 781 DictionaryValue* DictionaryValue::SetDictionary( 782 StringPiece path, 783 std::unique_ptr<DictionaryValue> in_value) { 784 return static_cast<DictionaryValue*>(Set(path, std::move(in_value))); 785 } 786 787 ListValue* DictionaryValue::SetList(StringPiece path, 788 std::unique_ptr<ListValue> in_value) { 789 return static_cast<ListValue*>(Set(path, std::move(in_value))); 790 } 791 792 Value* DictionaryValue::SetWithoutPathExpansion( 793 StringPiece key, 794 std::unique_ptr<Value> in_value) { 795 // NOTE: We can't use |insert_or_assign| here, as only |try_emplace| does 796 // an explicit conversion from StringPiece to std::string if necessary. 797 auto result = dict_.try_emplace(key, std::move(in_value)); 798 if (!result.second) { 799 // in_value is guaranteed to be still intact at this point. 800 result.first->second = std::move(in_value); 801 } 802 return result.first->second.get(); 803 } 804 805 bool DictionaryValue::Get(StringPiece path, 806 const Value** out_value) const { 807 DCHECK(IsStringUTF8(path)); 808 StringPiece current_path(path); 809 const DictionaryValue* current_dictionary = this; 810 for (size_t delimiter_position = current_path.find('.'); 811 delimiter_position != std::string::npos; 812 delimiter_position = current_path.find('.')) { 813 const DictionaryValue* child_dictionary = nullptr; 814 if (!current_dictionary->GetDictionaryWithoutPathExpansion( 815 current_path.substr(0, delimiter_position), &child_dictionary)) { 816 return false; 817 } 818 819 current_dictionary = child_dictionary; 820 current_path = current_path.substr(delimiter_position + 1); 821 } 822 823 return current_dictionary->GetWithoutPathExpansion(current_path, out_value); 824 } 825 826 bool DictionaryValue::Get(StringPiece path, Value** out_value) { 827 return static_cast<const DictionaryValue&>(*this).Get( 828 path, 829 const_cast<const Value**>(out_value)); 830 } 831 832 bool DictionaryValue::GetBoolean(StringPiece path, bool* bool_value) const { 833 const Value* value; 834 if (!Get(path, &value)) 835 return false; 836 837 return value->GetAsBoolean(bool_value); 838 } 839 840 bool DictionaryValue::GetInteger(StringPiece path, int* out_value) const { 841 const Value* value; 842 if (!Get(path, &value)) 843 return false; 844 845 return value->GetAsInteger(out_value); 846 } 847 848 bool DictionaryValue::GetDouble(StringPiece path, double* out_value) const { 849 const Value* value; 850 if (!Get(path, &value)) 851 return false; 852 853 return value->GetAsDouble(out_value); 854 } 855 856 bool DictionaryValue::GetString(StringPiece path, 857 std::string* out_value) const { 858 const Value* value; 859 if (!Get(path, &value)) 860 return false; 861 862 return value->GetAsString(out_value); 863 } 864 865 bool DictionaryValue::GetString(StringPiece path, string16* out_value) const { 866 const Value* value; 867 if (!Get(path, &value)) 868 return false; 869 870 return value->GetAsString(out_value); 871 } 872 873 bool DictionaryValue::GetStringASCII(StringPiece path, 874 std::string* out_value) const { 875 std::string out; 876 if (!GetString(path, &out)) 877 return false; 878 879 if (!IsStringASCII(out)) { 880 NOTREACHED(); 881 return false; 882 } 883 884 out_value->assign(out); 885 return true; 886 } 887 888 bool DictionaryValue::GetBinary(StringPiece path, 889 const Value** out_value) const { 890 const Value* value; 891 bool result = Get(path, &value); 892 if (!result || !value->is_blob()) 893 return false; 894 895 if (out_value) 896 *out_value = value; 897 898 return true; 899 } 900 901 bool DictionaryValue::GetBinary(StringPiece path, Value** out_value) { 902 return static_cast<const DictionaryValue&>(*this).GetBinary( 903 path, const_cast<const Value**>(out_value)); 904 } 905 906 bool DictionaryValue::GetDictionary(StringPiece path, 907 const DictionaryValue** out_value) const { 908 const Value* value; 909 bool result = Get(path, &value); 910 if (!result || !value->is_dict()) 911 return false; 912 913 if (out_value) 914 *out_value = static_cast<const DictionaryValue*>(value); 915 916 return true; 917 } 918 919 bool DictionaryValue::GetDictionary(StringPiece path, 920 DictionaryValue** out_value) { 921 return static_cast<const DictionaryValue&>(*this).GetDictionary( 922 path, 923 const_cast<const DictionaryValue**>(out_value)); 924 } 925 926 bool DictionaryValue::GetList(StringPiece path, 927 const ListValue** out_value) const { 928 const Value* value; 929 bool result = Get(path, &value); 930 if (!result || !value->is_list()) 931 return false; 932 933 if (out_value) 934 *out_value = static_cast<const ListValue*>(value); 935 936 return true; 937 } 938 939 bool DictionaryValue::GetList(StringPiece path, ListValue** out_value) { 940 return static_cast<const DictionaryValue&>(*this).GetList( 941 path, 942 const_cast<const ListValue**>(out_value)); 943 } 944 945 bool DictionaryValue::GetWithoutPathExpansion(StringPiece key, 946 const Value** out_value) const { 947 DCHECK(IsStringUTF8(key)); 948 auto entry_iterator = dict_.find(key); 949 if (entry_iterator == dict_.end()) 950 return false; 951 952 if (out_value) 953 *out_value = entry_iterator->second.get(); 954 return true; 955 } 956 957 bool DictionaryValue::GetWithoutPathExpansion(StringPiece key, 958 Value** out_value) { 959 return static_cast<const DictionaryValue&>(*this).GetWithoutPathExpansion( 960 key, 961 const_cast<const Value**>(out_value)); 962 } 963 964 bool DictionaryValue::GetBooleanWithoutPathExpansion(StringPiece key, 965 bool* out_value) const { 966 const Value* value; 967 if (!GetWithoutPathExpansion(key, &value)) 968 return false; 969 970 return value->GetAsBoolean(out_value); 971 } 972 973 bool DictionaryValue::GetIntegerWithoutPathExpansion(StringPiece key, 974 int* out_value) const { 975 const Value* value; 976 if (!GetWithoutPathExpansion(key, &value)) 977 return false; 978 979 return value->GetAsInteger(out_value); 980 } 981 982 bool DictionaryValue::GetDoubleWithoutPathExpansion(StringPiece key, 983 double* out_value) const { 984 const Value* value; 985 if (!GetWithoutPathExpansion(key, &value)) 986 return false; 987 988 return value->GetAsDouble(out_value); 989 } 990 991 bool DictionaryValue::GetStringWithoutPathExpansion( 992 StringPiece key, 993 std::string* out_value) const { 994 const Value* value; 995 if (!GetWithoutPathExpansion(key, &value)) 996 return false; 997 998 return value->GetAsString(out_value); 999 } 1000 1001 bool DictionaryValue::GetStringWithoutPathExpansion(StringPiece key, 1002 string16* out_value) const { 1003 const Value* value; 1004 if (!GetWithoutPathExpansion(key, &value)) 1005 return false; 1006 1007 return value->GetAsString(out_value); 1008 } 1009 1010 bool DictionaryValue::GetDictionaryWithoutPathExpansion( 1011 StringPiece key, 1012 const DictionaryValue** out_value) const { 1013 const Value* value; 1014 bool result = GetWithoutPathExpansion(key, &value); 1015 if (!result || !value->is_dict()) 1016 return false; 1017 1018 if (out_value) 1019 *out_value = static_cast<const DictionaryValue*>(value); 1020 1021 return true; 1022 } 1023 1024 bool DictionaryValue::GetDictionaryWithoutPathExpansion( 1025 StringPiece key, 1026 DictionaryValue** out_value) { 1027 const DictionaryValue& const_this = 1028 static_cast<const DictionaryValue&>(*this); 1029 return const_this.GetDictionaryWithoutPathExpansion( 1030 key, 1031 const_cast<const DictionaryValue**>(out_value)); 1032 } 1033 1034 bool DictionaryValue::GetListWithoutPathExpansion( 1035 StringPiece key, 1036 const ListValue** out_value) const { 1037 const Value* value; 1038 bool result = GetWithoutPathExpansion(key, &value); 1039 if (!result || !value->is_list()) 1040 return false; 1041 1042 if (out_value) 1043 *out_value = static_cast<const ListValue*>(value); 1044 1045 return true; 1046 } 1047 1048 bool DictionaryValue::GetListWithoutPathExpansion(StringPiece key, 1049 ListValue** out_value) { 1050 return 1051 static_cast<const DictionaryValue&>(*this).GetListWithoutPathExpansion( 1052 key, 1053 const_cast<const ListValue**>(out_value)); 1054 } 1055 1056 bool DictionaryValue::Remove(StringPiece path, 1057 std::unique_ptr<Value>* out_value) { 1058 DCHECK(IsStringUTF8(path)); 1059 StringPiece current_path(path); 1060 DictionaryValue* current_dictionary = this; 1061 size_t delimiter_position = current_path.rfind('.'); 1062 if (delimiter_position != StringPiece::npos) { 1063 if (!GetDictionary(current_path.substr(0, delimiter_position), 1064 ¤t_dictionary)) 1065 return false; 1066 current_path = current_path.substr(delimiter_position + 1); 1067 } 1068 1069 return current_dictionary->RemoveWithoutPathExpansion(current_path, 1070 out_value); 1071 } 1072 1073 bool DictionaryValue::RemoveWithoutPathExpansion( 1074 StringPiece key, 1075 std::unique_ptr<Value>* out_value) { 1076 DCHECK(IsStringUTF8(key)); 1077 auto entry_iterator = dict_.find(key); 1078 if (entry_iterator == dict_.end()) 1079 return false; 1080 1081 if (out_value) 1082 *out_value = std::move(entry_iterator->second); 1083 dict_.erase(entry_iterator); 1084 return true; 1085 } 1086 1087 bool DictionaryValue::RemovePath(StringPiece path, 1088 std::unique_ptr<Value>* out_value) { 1089 bool result = false; 1090 size_t delimiter_position = path.find('.'); 1091 1092 if (delimiter_position == std::string::npos) 1093 return RemoveWithoutPathExpansion(path, out_value); 1094 1095 StringPiece subdict_path = path.substr(0, delimiter_position); 1096 DictionaryValue* subdict = nullptr; 1097 if (!GetDictionary(subdict_path, &subdict)) 1098 return false; 1099 result = subdict->RemovePath(path.substr(delimiter_position + 1), 1100 out_value); 1101 if (result && subdict->empty()) 1102 RemoveWithoutPathExpansion(subdict_path, nullptr); 1103 1104 return result; 1105 } 1106 1107 std::unique_ptr<DictionaryValue> DictionaryValue::DeepCopyWithoutEmptyChildren() 1108 const { 1109 std::unique_ptr<DictionaryValue> copy = 1110 CopyDictionaryWithoutEmptyChildren(*this); 1111 if (!copy) 1112 copy = std::make_unique<DictionaryValue>(); 1113 return copy; 1114 } 1115 1116 void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) { 1117 CHECK(dictionary->is_dict()); 1118 for (DictionaryValue::Iterator it(*dictionary); !it.IsAtEnd(); it.Advance()) { 1119 const Value* merge_value = &it.value(); 1120 // Check whether we have to merge dictionaries. 1121 if (merge_value->is_dict()) { 1122 DictionaryValue* sub_dict; 1123 if (GetDictionaryWithoutPathExpansion(it.key(), &sub_dict)) { 1124 sub_dict->MergeDictionary( 1125 static_cast<const DictionaryValue*>(merge_value)); 1126 continue; 1127 } 1128 } 1129 // All other cases: Make a copy and hook it up. 1130 SetKey(it.key(), merge_value->Clone()); 1131 } 1132 } 1133 1134 void DictionaryValue::Swap(DictionaryValue* other) { 1135 CHECK(other->is_dict()); 1136 dict_.swap(other->dict_); 1137 } 1138 1139 DictionaryValue::Iterator::Iterator(const DictionaryValue& target) 1140 : target_(target), it_(target.dict_.begin()) {} 1141 1142 DictionaryValue::Iterator::Iterator(const Iterator& other) = default; 1143 1144 DictionaryValue::Iterator::~Iterator() = default; 1145 1146 DictionaryValue* DictionaryValue::DeepCopy() const { 1147 return new DictionaryValue(dict_); 1148 } 1149 1150 std::unique_ptr<DictionaryValue> DictionaryValue::CreateDeepCopy() const { 1151 return std::make_unique<DictionaryValue>(dict_); 1152 } 1153 1154 ///////////////////// ListValue //////////////////// 1155 1156 // static 1157 std::unique_ptr<ListValue> ListValue::From(std::unique_ptr<Value> value) { 1158 ListValue* out; 1159 if (value && value->GetAsList(&out)) { 1160 ignore_result(value.release()); 1161 return WrapUnique(out); 1162 } 1163 return nullptr; 1164 } 1165 1166 ListValue::ListValue() : Value(Type::LIST) {} 1167 ListValue::ListValue(const ListStorage& in_list) : Value(in_list) {} 1168 ListValue::ListValue(ListStorage&& in_list) noexcept 1169 : Value(std::move(in_list)) {} 1170 1171 void ListValue::Clear() { 1172 list_.clear(); 1173 } 1174 1175 void ListValue::Reserve(size_t n) { 1176 list_.reserve(n); 1177 } 1178 1179 bool ListValue::Set(size_t index, std::unique_ptr<Value> in_value) { 1180 if (!in_value) 1181 return false; 1182 1183 if (index >= list_.size()) 1184 list_.resize(index + 1); 1185 1186 list_[index] = std::move(*in_value); 1187 return true; 1188 } 1189 1190 bool ListValue::Get(size_t index, const Value** out_value) const { 1191 if (index >= list_.size()) 1192 return false; 1193 1194 if (out_value) 1195 *out_value = &list_[index]; 1196 1197 return true; 1198 } 1199 1200 bool ListValue::Get(size_t index, Value** out_value) { 1201 return static_cast<const ListValue&>(*this).Get( 1202 index, 1203 const_cast<const Value**>(out_value)); 1204 } 1205 1206 bool ListValue::GetBoolean(size_t index, bool* bool_value) const { 1207 const Value* value; 1208 if (!Get(index, &value)) 1209 return false; 1210 1211 return value->GetAsBoolean(bool_value); 1212 } 1213 1214 bool ListValue::GetInteger(size_t index, int* out_value) const { 1215 const Value* value; 1216 if (!Get(index, &value)) 1217 return false; 1218 1219 return value->GetAsInteger(out_value); 1220 } 1221 1222 bool ListValue::GetDouble(size_t index, double* out_value) const { 1223 const Value* value; 1224 if (!Get(index, &value)) 1225 return false; 1226 1227 return value->GetAsDouble(out_value); 1228 } 1229 1230 bool ListValue::GetString(size_t index, std::string* out_value) const { 1231 const Value* value; 1232 if (!Get(index, &value)) 1233 return false; 1234 1235 return value->GetAsString(out_value); 1236 } 1237 1238 bool ListValue::GetString(size_t index, string16* out_value) const { 1239 const Value* value; 1240 if (!Get(index, &value)) 1241 return false; 1242 1243 return value->GetAsString(out_value); 1244 } 1245 1246 bool ListValue::GetDictionary(size_t index, 1247 const DictionaryValue** out_value) const { 1248 const Value* value; 1249 bool result = Get(index, &value); 1250 if (!result || !value->is_dict()) 1251 return false; 1252 1253 if (out_value) 1254 *out_value = static_cast<const DictionaryValue*>(value); 1255 1256 return true; 1257 } 1258 1259 bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) { 1260 return static_cast<const ListValue&>(*this).GetDictionary( 1261 index, 1262 const_cast<const DictionaryValue**>(out_value)); 1263 } 1264 1265 bool ListValue::GetList(size_t index, const ListValue** out_value) const { 1266 const Value* value; 1267 bool result = Get(index, &value); 1268 if (!result || !value->is_list()) 1269 return false; 1270 1271 if (out_value) 1272 *out_value = static_cast<const ListValue*>(value); 1273 1274 return true; 1275 } 1276 1277 bool ListValue::GetList(size_t index, ListValue** out_value) { 1278 return static_cast<const ListValue&>(*this).GetList( 1279 index, 1280 const_cast<const ListValue**>(out_value)); 1281 } 1282 1283 bool ListValue::Remove(size_t index, std::unique_ptr<Value>* out_value) { 1284 if (index >= list_.size()) 1285 return false; 1286 1287 if (out_value) 1288 *out_value = std::make_unique<Value>(std::move(list_[index])); 1289 1290 list_.erase(list_.begin() + index); 1291 return true; 1292 } 1293 1294 bool ListValue::Remove(const Value& value, size_t* index) { 1295 auto it = std::find(list_.begin(), list_.end(), value); 1296 1297 if (it == list_.end()) 1298 return false; 1299 1300 if (index) 1301 *index = std::distance(list_.begin(), it); 1302 1303 list_.erase(it); 1304 return true; 1305 } 1306 1307 ListValue::iterator ListValue::Erase(iterator iter, 1308 std::unique_ptr<Value>* out_value) { 1309 if (out_value) 1310 *out_value = std::make_unique<Value>(std::move(*iter)); 1311 1312 return list_.erase(iter); 1313 } 1314 1315 void ListValue::Append(std::unique_ptr<Value> in_value) { 1316 list_.push_back(std::move(*in_value)); 1317 } 1318 1319 void ListValue::AppendBoolean(bool in_value) { 1320 list_.emplace_back(in_value); 1321 } 1322 1323 void ListValue::AppendInteger(int in_value) { 1324 list_.emplace_back(in_value); 1325 } 1326 1327 void ListValue::AppendDouble(double in_value) { 1328 list_.emplace_back(in_value); 1329 } 1330 1331 void ListValue::AppendString(StringPiece in_value) { 1332 list_.emplace_back(in_value); 1333 } 1334 1335 void ListValue::AppendString(const string16& in_value) { 1336 list_.emplace_back(in_value); 1337 } 1338 1339 void ListValue::AppendStrings(const std::vector<std::string>& in_values) { 1340 list_.reserve(list_.size() + in_values.size()); 1341 for (const auto& in_value : in_values) 1342 list_.emplace_back(in_value); 1343 } 1344 1345 void ListValue::AppendStrings(const std::vector<string16>& in_values) { 1346 list_.reserve(list_.size() + in_values.size()); 1347 for (const auto& in_value : in_values) 1348 list_.emplace_back(in_value); 1349 } 1350 1351 bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) { 1352 DCHECK(in_value); 1353 if (ContainsValue(list_, *in_value)) 1354 return false; 1355 1356 list_.push_back(std::move(*in_value)); 1357 return true; 1358 } 1359 1360 bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) { 1361 DCHECK(in_value); 1362 if (index > list_.size()) 1363 return false; 1364 1365 list_.insert(list_.begin() + index, std::move(*in_value)); 1366 return true; 1367 } 1368 1369 ListValue::const_iterator ListValue::Find(const Value& value) const { 1370 return std::find(list_.begin(), list_.end(), value); 1371 } 1372 1373 void ListValue::Swap(ListValue* other) { 1374 CHECK(other->is_list()); 1375 list_.swap(other->list_); 1376 } 1377 1378 ListValue* ListValue::DeepCopy() const { 1379 return new ListValue(list_); 1380 } 1381 1382 std::unique_ptr<ListValue> ListValue::CreateDeepCopy() const { 1383 return std::make_unique<ListValue>(list_); 1384 } 1385 1386 ValueSerializer::~ValueSerializer() = default; 1387 1388 ValueDeserializer::~ValueDeserializer() = default; 1389 1390 std::ostream& operator<<(std::ostream& out, const Value& value) { 1391 std::string json; 1392 JSONWriter::WriteWithOptions(value, JSONWriter::OPTIONS_PRETTY_PRINT, &json); 1393 return out << json; 1394 } 1395 1396 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { 1397 if (static_cast<int>(type) < 0 || 1398 static_cast<size_t>(type) >= arraysize(kTypeNames)) 1399 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; 1400 return out << Value::GetTypeName(type); 1401 } 1402 1403 } // namespace base 1404