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