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/move.h" 17#include "base/strings/string_util.h" 18#include "base/strings/utf_string_conversion_utils.h" 19 20namespace base { 21 22namespace { 23 24scoped_ptr<Value> CopyWithoutEmptyChildren(const Value& node); 25 26// Make a deep copy of |node|, but don't include empty lists or dictionaries 27// in the copy. It's possible for this function to return NULL and it 28// expects |node| to always be non-NULL. 29scoped_ptr<ListValue> CopyListWithoutEmptyChildren(const ListValue& list) { 30 scoped_ptr<ListValue> copy; 31 for (ListValue::const_iterator it = list.begin(); it != list.end(); ++it) { 32 scoped_ptr<Value> child_copy = CopyWithoutEmptyChildren(**it); 33 if (child_copy) { 34 if (!copy) 35 copy.reset(new ListValue); 36 copy->Append(std::move(child_copy)); 37 } 38 } 39 return copy; 40} 41 42scoped_ptr<DictionaryValue> CopyDictionaryWithoutEmptyChildren( 43 const DictionaryValue& dict) { 44 scoped_ptr<DictionaryValue> copy; 45 for (DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { 46 scoped_ptr<Value> child_copy = CopyWithoutEmptyChildren(it.value()); 47 if (child_copy) { 48 if (!copy) 49 copy.reset(new DictionaryValue); 50 copy->SetWithoutPathExpansion(it.key(), std::move(child_copy)); 51 } 52 } 53 return copy; 54} 55 56scoped_ptr<Value> CopyWithoutEmptyChildren(const Value& node) { 57 switch (node.GetType()) { 58 case Value::TYPE_LIST: 59 return CopyListWithoutEmptyChildren(static_cast<const ListValue&>(node)); 60 61 case Value::TYPE_DICTIONARY: 62 return CopyDictionaryWithoutEmptyChildren( 63 static_cast<const DictionaryValue&>(node)); 64 65 default: 66 return node.CreateDeepCopy(); 67 } 68} 69 70// A small functor for comparing Values for std::find_if and similar. 71class ValueEquals { 72 public: 73 // Pass the value against which all consecutive calls of the () operator will 74 // compare their argument to. This Value object must not be destroyed while 75 // the ValueEquals is in use. 76 explicit ValueEquals(const Value* first) : first_(first) { } 77 78 bool operator ()(const Value* second) const { 79 return first_->Equals(second); 80 } 81 82 private: 83 const Value* first_; 84}; 85 86} // namespace 87 88Value::~Value() { 89} 90 91// static 92scoped_ptr<Value> Value::CreateNullValue() { 93 return make_scoped_ptr(new Value(TYPE_NULL)); 94} 95 96bool Value::GetAsBinary(const BinaryValue** /* out_value */) const { 97 return false; 98} 99 100bool Value::GetAsBoolean(bool* /* out_value */) const { 101 return false; 102} 103 104bool Value::GetAsInteger(int* /* out_value */) const { 105 return false; 106} 107 108bool Value::GetAsDouble(double* /* out_value */) const { 109 return false; 110} 111 112bool Value::GetAsString(std::string* /* out_value */) const { 113 return false; 114} 115 116bool Value::GetAsString(const StringValue** out_value) const { 117 return false; 118} 119 120bool Value::GetAsList(ListValue** /* out_value */) { 121 return false; 122} 123 124bool Value::GetAsList(const ListValue** /* out_value */) const { 125 return false; 126} 127 128bool Value::GetAsDictionary(DictionaryValue** /* out_value */) { 129 return false; 130} 131 132bool Value::GetAsDictionary(const DictionaryValue** /* out_value */) const { 133 return false; 134} 135 136Value* Value::DeepCopy() const { 137 // This method should only be getting called for null Values--all subclasses 138 // need to provide their own implementation;. 139 DCHECK(IsType(TYPE_NULL)); 140 return CreateNullValue().release(); 141} 142 143scoped_ptr<Value> Value::CreateDeepCopy() const { 144 return make_scoped_ptr(DeepCopy()); 145} 146 147bool Value::Equals(const Value* other) const { 148 // This method should only be getting called for null Values--all subclasses 149 // need to provide their own implementation;. 150 DCHECK(IsType(TYPE_NULL)); 151 return other->IsType(TYPE_NULL); 152} 153 154// static 155bool Value::Equals(const Value* a, const Value* b) { 156 if ((a == NULL) && (b == NULL)) return true; 157 if ((a == NULL) ^ (b == NULL)) return false; 158 return a->Equals(b); 159} 160 161Value::Value(Type type) : type_(type) {} 162 163Value::Value(const Value& that) : type_(that.type_) {} 164 165Value& Value::operator=(const Value& that) { 166 type_ = that.type_; 167 return *this; 168} 169 170///////////////////// FundamentalValue //////////////////// 171 172FundamentalValue::FundamentalValue(bool in_value) 173 : Value(TYPE_BOOLEAN), boolean_value_(in_value) { 174} 175 176FundamentalValue::FundamentalValue(int in_value) 177 : Value(TYPE_INTEGER), integer_value_(in_value) { 178} 179 180FundamentalValue::FundamentalValue(double in_value) 181 : Value(TYPE_DOUBLE), double_value_(in_value) { 182 if (!std::isfinite(double_value_)) { 183 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) " 184 << "values cannot be represented in JSON"; 185 double_value_ = 0.0; 186 } 187} 188 189FundamentalValue::~FundamentalValue() { 190} 191 192bool FundamentalValue::GetAsBoolean(bool* out_value) const { 193 if (out_value && IsType(TYPE_BOOLEAN)) 194 *out_value = boolean_value_; 195 return (IsType(TYPE_BOOLEAN)); 196} 197 198bool FundamentalValue::GetAsInteger(int* out_value) const { 199 if (out_value && IsType(TYPE_INTEGER)) 200 *out_value = integer_value_; 201 return (IsType(TYPE_INTEGER)); 202} 203 204bool FundamentalValue::GetAsDouble(double* out_value) const { 205 if (out_value && IsType(TYPE_DOUBLE)) 206 *out_value = double_value_; 207 else if (out_value && IsType(TYPE_INTEGER)) 208 *out_value = integer_value_; 209 return (IsType(TYPE_DOUBLE) || IsType(TYPE_INTEGER)); 210} 211 212FundamentalValue* FundamentalValue::DeepCopy() const { 213 switch (GetType()) { 214 case TYPE_BOOLEAN: 215 return new FundamentalValue(boolean_value_); 216 217 case TYPE_INTEGER: 218 return new FundamentalValue(integer_value_); 219 220 case TYPE_DOUBLE: 221 return new FundamentalValue(double_value_); 222 223 default: 224 NOTREACHED(); 225 return NULL; 226 } 227} 228 229bool FundamentalValue::Equals(const Value* other) const { 230 if (other->GetType() != GetType()) 231 return false; 232 233 switch (GetType()) { 234 case TYPE_BOOLEAN: { 235 bool lhs, rhs; 236 return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs; 237 } 238 case TYPE_INTEGER: { 239 int lhs, rhs; 240 return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs; 241 } 242 case TYPE_DOUBLE: { 243 double lhs, rhs; 244 return GetAsDouble(&lhs) && other->GetAsDouble(&rhs) && lhs == rhs; 245 } 246 default: 247 NOTREACHED(); 248 return false; 249 } 250} 251 252///////////////////// StringValue //////////////////// 253 254StringValue::StringValue(const std::string& in_value) 255 : Value(TYPE_STRING), 256 value_(in_value) { 257 DCHECK(IsStringUTF8(in_value)); 258} 259 260StringValue::~StringValue() { 261} 262 263std::string* StringValue::GetString() { 264 return &value_; 265} 266 267const std::string& StringValue::GetString() const { 268 return value_; 269} 270 271bool StringValue::GetAsString(std::string* out_value) const { 272 if (out_value) 273 *out_value = value_; 274 return true; 275} 276 277bool StringValue::GetAsString(const StringValue** out_value) const { 278 if (out_value) 279 *out_value = this; 280 return true; 281} 282 283StringValue* StringValue::DeepCopy() const { 284 return new StringValue(value_); 285} 286 287bool StringValue::Equals(const Value* other) const { 288 if (other->GetType() != GetType()) 289 return false; 290 std::string lhs, rhs; 291 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs; 292} 293 294///////////////////// BinaryValue //////////////////// 295 296BinaryValue::BinaryValue() 297 : Value(TYPE_BINARY), 298 size_(0) { 299} 300 301BinaryValue::BinaryValue(scoped_ptr<char[]> buffer, size_t size) 302 : Value(TYPE_BINARY), buffer_(std::move(buffer)), size_(size) {} 303 304BinaryValue::~BinaryValue() { 305} 306 307// static 308BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer, 309 size_t size) { 310 char* buffer_copy = new char[size]; 311 memcpy(buffer_copy, buffer, size); 312 scoped_ptr<char[]> scoped_buffer_copy(buffer_copy); 313 return new BinaryValue(std::move(scoped_buffer_copy), size); 314} 315 316bool BinaryValue::GetAsBinary(const BinaryValue** out_value) const { 317 if (out_value) 318 *out_value = this; 319 return true; 320} 321 322BinaryValue* BinaryValue::DeepCopy() const { 323 return CreateWithCopiedBuffer(buffer_.get(), size_); 324} 325 326bool BinaryValue::Equals(const Value* other) const { 327 if (other->GetType() != GetType()) 328 return false; 329 const BinaryValue* other_binary = static_cast<const BinaryValue*>(other); 330 if (other_binary->size_ != size_) 331 return false; 332 return !memcmp(GetBuffer(), other_binary->GetBuffer(), size_); 333} 334 335///////////////////// DictionaryValue //////////////////// 336 337// static 338scoped_ptr<DictionaryValue> DictionaryValue::From(scoped_ptr<Value> value) { 339 DictionaryValue* out; 340 if (value && value->GetAsDictionary(&out)) { 341 ignore_result(value.release()); 342 return make_scoped_ptr(out); 343 } 344 return nullptr; 345} 346 347DictionaryValue::DictionaryValue() 348 : Value(TYPE_DICTIONARY) { 349} 350 351DictionaryValue::~DictionaryValue() { 352 Clear(); 353} 354 355bool DictionaryValue::GetAsDictionary(DictionaryValue** out_value) { 356 if (out_value) 357 *out_value = this; 358 return true; 359} 360 361bool DictionaryValue::GetAsDictionary(const DictionaryValue** out_value) const { 362 if (out_value) 363 *out_value = this; 364 return true; 365} 366 367bool DictionaryValue::HasKey(const std::string& key) const { 368 DCHECK(IsStringUTF8(key)); 369 ValueMap::const_iterator current_entry = dictionary_.find(key); 370 DCHECK((current_entry == dictionary_.end()) || current_entry->second); 371 return current_entry != dictionary_.end(); 372} 373 374void DictionaryValue::Clear() { 375 ValueMap::iterator dict_iterator = dictionary_.begin(); 376 while (dict_iterator != dictionary_.end()) { 377 delete dict_iterator->second; 378 ++dict_iterator; 379 } 380 381 dictionary_.clear(); 382} 383 384void DictionaryValue::Set(const std::string& path, scoped_ptr<Value> in_value) { 385 DCHECK(IsStringUTF8(path)); 386 DCHECK(in_value); 387 388 std::string current_path(path); 389 DictionaryValue* current_dictionary = this; 390 for (size_t delimiter_position = current_path.find('.'); 391 delimiter_position != std::string::npos; 392 delimiter_position = current_path.find('.')) { 393 // Assume that we're indexing into a dictionary. 394 std::string key(current_path, 0, delimiter_position); 395 DictionaryValue* child_dictionary = NULL; 396 if (!current_dictionary->GetDictionary(key, &child_dictionary)) { 397 child_dictionary = new DictionaryValue; 398 current_dictionary->SetWithoutPathExpansion(key, child_dictionary); 399 } 400 401 current_dictionary = child_dictionary; 402 current_path.erase(0, delimiter_position + 1); 403 } 404 405 current_dictionary->SetWithoutPathExpansion(current_path, 406 std::move(in_value)); 407} 408 409void DictionaryValue::Set(const std::string& path, Value* in_value) { 410 Set(path, make_scoped_ptr(in_value)); 411} 412 413void DictionaryValue::SetBoolean(const std::string& path, bool in_value) { 414 Set(path, new FundamentalValue(in_value)); 415} 416 417void DictionaryValue::SetInteger(const std::string& path, int in_value) { 418 Set(path, new FundamentalValue(in_value)); 419} 420 421void DictionaryValue::SetDouble(const std::string& path, double in_value) { 422 Set(path, new FundamentalValue(in_value)); 423} 424 425void DictionaryValue::SetString(const std::string& path, 426 const std::string& in_value) { 427 Set(path, new StringValue(in_value)); 428} 429 430void DictionaryValue::SetWithoutPathExpansion(const std::string& key, 431 scoped_ptr<Value> in_value) { 432 Value* bare_ptr = in_value.release(); 433 // If there's an existing value here, we need to delete it, because 434 // we own all our children. 435 std::pair<ValueMap::iterator, bool> ins_res = 436 dictionary_.insert(std::make_pair(key, bare_ptr)); 437 if (!ins_res.second) { 438 DCHECK_NE(ins_res.first->second, bare_ptr); // This would be bogus 439 delete ins_res.first->second; 440 ins_res.first->second = bare_ptr; 441 } 442} 443 444void DictionaryValue::SetWithoutPathExpansion(const std::string& key, 445 Value* in_value) { 446 SetWithoutPathExpansion(key, make_scoped_ptr(in_value)); 447} 448 449void DictionaryValue::SetBooleanWithoutPathExpansion( 450 const std::string& path, bool in_value) { 451 SetWithoutPathExpansion(path, new FundamentalValue(in_value)); 452} 453 454void DictionaryValue::SetIntegerWithoutPathExpansion( 455 const std::string& path, int in_value) { 456 SetWithoutPathExpansion(path, new FundamentalValue(in_value)); 457} 458 459void DictionaryValue::SetDoubleWithoutPathExpansion( 460 const std::string& path, double in_value) { 461 SetWithoutPathExpansion(path, new FundamentalValue(in_value)); 462} 463 464void DictionaryValue::SetStringWithoutPathExpansion( 465 const std::string& path, const std::string& in_value) { 466 SetWithoutPathExpansion(path, new StringValue(in_value)); 467} 468 469bool DictionaryValue::Get(StringPiece path, 470 const Value** out_value) const { 471 DCHECK(IsStringUTF8(path)); 472 StringPiece current_path(path); 473 const DictionaryValue* current_dictionary = this; 474 for (size_t delimiter_position = current_path.find('.'); 475 delimiter_position != std::string::npos; 476 delimiter_position = current_path.find('.')) { 477 const DictionaryValue* child_dictionary = NULL; 478 if (!current_dictionary->GetDictionaryWithoutPathExpansion( 479 current_path.substr(0, delimiter_position).as_string(), 480 &child_dictionary)) { 481 return false; 482 } 483 484 current_dictionary = child_dictionary; 485 current_path = current_path.substr(delimiter_position + 1); 486 } 487 488 return current_dictionary->GetWithoutPathExpansion(current_path.as_string(), 489 out_value); 490} 491 492bool DictionaryValue::Get(StringPiece path, Value** out_value) { 493 return static_cast<const DictionaryValue&>(*this).Get( 494 path, 495 const_cast<const Value**>(out_value)); 496} 497 498bool DictionaryValue::GetBoolean(const std::string& path, 499 bool* bool_value) const { 500 const Value* value; 501 if (!Get(path, &value)) 502 return false; 503 504 return value->GetAsBoolean(bool_value); 505} 506 507bool DictionaryValue::GetInteger(const std::string& path, 508 int* out_value) const { 509 const Value* value; 510 if (!Get(path, &value)) 511 return false; 512 513 return value->GetAsInteger(out_value); 514} 515 516bool DictionaryValue::GetDouble(const std::string& path, 517 double* out_value) const { 518 const Value* value; 519 if (!Get(path, &value)) 520 return false; 521 522 return value->GetAsDouble(out_value); 523} 524 525bool DictionaryValue::GetString(const std::string& path, 526 std::string* out_value) const { 527 const Value* value; 528 if (!Get(path, &value)) 529 return false; 530 531 return value->GetAsString(out_value); 532} 533 534bool DictionaryValue::GetStringASCII(const std::string& path, 535 std::string* out_value) const { 536 std::string out; 537 if (!GetString(path, &out)) 538 return false; 539 540 if (!IsStringASCII(out)) { 541 NOTREACHED(); 542 return false; 543 } 544 545 out_value->assign(out); 546 return true; 547} 548 549bool DictionaryValue::GetBinary(const std::string& path, 550 const BinaryValue** out_value) const { 551 const Value* value; 552 bool result = Get(path, &value); 553 if (!result || !value->IsType(TYPE_BINARY)) 554 return false; 555 556 if (out_value) 557 *out_value = static_cast<const BinaryValue*>(value); 558 559 return true; 560} 561 562bool DictionaryValue::GetBinary(const std::string& path, 563 BinaryValue** out_value) { 564 return static_cast<const DictionaryValue&>(*this).GetBinary( 565 path, 566 const_cast<const BinaryValue**>(out_value)); 567} 568 569bool DictionaryValue::GetDictionary(StringPiece path, 570 const DictionaryValue** out_value) const { 571 const Value* value; 572 bool result = Get(path, &value); 573 if (!result || !value->IsType(TYPE_DICTIONARY)) 574 return false; 575 576 if (out_value) 577 *out_value = static_cast<const DictionaryValue*>(value); 578 579 return true; 580} 581 582bool DictionaryValue::GetDictionary(StringPiece path, 583 DictionaryValue** out_value) { 584 return static_cast<const DictionaryValue&>(*this).GetDictionary( 585 path, 586 const_cast<const DictionaryValue**>(out_value)); 587} 588 589bool DictionaryValue::GetList(const std::string& path, 590 const ListValue** out_value) const { 591 const Value* value; 592 bool result = Get(path, &value); 593 if (!result || !value->IsType(TYPE_LIST)) 594 return false; 595 596 if (out_value) 597 *out_value = static_cast<const ListValue*>(value); 598 599 return true; 600} 601 602bool DictionaryValue::GetList(const std::string& path, ListValue** out_value) { 603 return static_cast<const DictionaryValue&>(*this).GetList( 604 path, 605 const_cast<const ListValue**>(out_value)); 606} 607 608bool DictionaryValue::GetWithoutPathExpansion(const std::string& key, 609 const Value** out_value) const { 610 DCHECK(IsStringUTF8(key)); 611 ValueMap::const_iterator entry_iterator = dictionary_.find(key); 612 if (entry_iterator == dictionary_.end()) 613 return false; 614 615 const Value* entry = entry_iterator->second; 616 if (out_value) 617 *out_value = entry; 618 return true; 619} 620 621bool DictionaryValue::GetWithoutPathExpansion(const std::string& key, 622 Value** out_value) { 623 return static_cast<const DictionaryValue&>(*this).GetWithoutPathExpansion( 624 key, 625 const_cast<const Value**>(out_value)); 626} 627 628bool DictionaryValue::GetBooleanWithoutPathExpansion(const std::string& key, 629 bool* out_value) const { 630 const Value* value; 631 if (!GetWithoutPathExpansion(key, &value)) 632 return false; 633 634 return value->GetAsBoolean(out_value); 635} 636 637bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::string& key, 638 int* out_value) const { 639 const Value* value; 640 if (!GetWithoutPathExpansion(key, &value)) 641 return false; 642 643 return value->GetAsInteger(out_value); 644} 645 646bool DictionaryValue::GetDoubleWithoutPathExpansion(const std::string& key, 647 double* out_value) const { 648 const Value* value; 649 if (!GetWithoutPathExpansion(key, &value)) 650 return false; 651 652 return value->GetAsDouble(out_value); 653} 654 655bool DictionaryValue::GetStringWithoutPathExpansion( 656 const std::string& key, 657 std::string* out_value) const { 658 const Value* value; 659 if (!GetWithoutPathExpansion(key, &value)) 660 return false; 661 662 return value->GetAsString(out_value); 663} 664 665bool DictionaryValue::GetDictionaryWithoutPathExpansion( 666 const std::string& key, 667 const DictionaryValue** out_value) const { 668 const Value* value; 669 bool result = GetWithoutPathExpansion(key, &value); 670 if (!result || !value->IsType(TYPE_DICTIONARY)) 671 return false; 672 673 if (out_value) 674 *out_value = static_cast<const DictionaryValue*>(value); 675 676 return true; 677} 678 679bool DictionaryValue::GetDictionaryWithoutPathExpansion( 680 const std::string& key, 681 DictionaryValue** out_value) { 682 const DictionaryValue& const_this = 683 static_cast<const DictionaryValue&>(*this); 684 return const_this.GetDictionaryWithoutPathExpansion( 685 key, 686 const_cast<const DictionaryValue**>(out_value)); 687} 688 689bool DictionaryValue::GetListWithoutPathExpansion( 690 const std::string& key, 691 const ListValue** out_value) const { 692 const Value* value; 693 bool result = GetWithoutPathExpansion(key, &value); 694 if (!result || !value->IsType(TYPE_LIST)) 695 return false; 696 697 if (out_value) 698 *out_value = static_cast<const ListValue*>(value); 699 700 return true; 701} 702 703bool DictionaryValue::GetListWithoutPathExpansion(const std::string& key, 704 ListValue** out_value) { 705 return 706 static_cast<const DictionaryValue&>(*this).GetListWithoutPathExpansion( 707 key, 708 const_cast<const ListValue**>(out_value)); 709} 710 711bool DictionaryValue::Remove(const std::string& path, 712 scoped_ptr<Value>* out_value) { 713 DCHECK(IsStringUTF8(path)); 714 std::string current_path(path); 715 DictionaryValue* current_dictionary = this; 716 size_t delimiter_position = current_path.rfind('.'); 717 if (delimiter_position != std::string::npos) { 718 if (!GetDictionary(current_path.substr(0, delimiter_position), 719 ¤t_dictionary)) 720 return false; 721 current_path.erase(0, delimiter_position + 1); 722 } 723 724 return current_dictionary->RemoveWithoutPathExpansion(current_path, 725 out_value); 726} 727 728bool DictionaryValue::RemoveWithoutPathExpansion(const std::string& key, 729 scoped_ptr<Value>* out_value) { 730 DCHECK(IsStringUTF8(key)); 731 ValueMap::iterator entry_iterator = dictionary_.find(key); 732 if (entry_iterator == dictionary_.end()) 733 return false; 734 735 Value* entry = entry_iterator->second; 736 if (out_value) 737 out_value->reset(entry); 738 else 739 delete entry; 740 dictionary_.erase(entry_iterator); 741 return true; 742} 743 744bool DictionaryValue::RemovePath(const std::string& path, 745 scoped_ptr<Value>* out_value) { 746 bool result = false; 747 size_t delimiter_position = path.find('.'); 748 749 if (delimiter_position == std::string::npos) 750 return RemoveWithoutPathExpansion(path, out_value); 751 752 const std::string subdict_path = path.substr(0, delimiter_position); 753 DictionaryValue* subdict = NULL; 754 if (!GetDictionary(subdict_path, &subdict)) 755 return false; 756 result = subdict->RemovePath(path.substr(delimiter_position + 1), 757 out_value); 758 if (result && subdict->empty()) 759 RemoveWithoutPathExpansion(subdict_path, NULL); 760 761 return result; 762} 763 764scoped_ptr<DictionaryValue> DictionaryValue::DeepCopyWithoutEmptyChildren() 765 const { 766 scoped_ptr<DictionaryValue> copy = CopyDictionaryWithoutEmptyChildren(*this); 767 if (!copy) 768 copy.reset(new DictionaryValue); 769 return copy; 770} 771 772void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) { 773 for (DictionaryValue::Iterator it(*dictionary); !it.IsAtEnd(); it.Advance()) { 774 const Value* merge_value = &it.value(); 775 // Check whether we have to merge dictionaries. 776 if (merge_value->IsType(Value::TYPE_DICTIONARY)) { 777 DictionaryValue* sub_dict; 778 if (GetDictionaryWithoutPathExpansion(it.key(), &sub_dict)) { 779 sub_dict->MergeDictionary( 780 static_cast<const DictionaryValue*>(merge_value)); 781 continue; 782 } 783 } 784 // All other cases: Make a copy and hook it up. 785 SetWithoutPathExpansion(it.key(), merge_value->DeepCopy()); 786 } 787} 788 789void DictionaryValue::Swap(DictionaryValue* other) { 790 dictionary_.swap(other->dictionary_); 791} 792 793DictionaryValue::Iterator::Iterator(const DictionaryValue& target) 794 : target_(target), 795 it_(target.dictionary_.begin()) {} 796 797DictionaryValue::Iterator::~Iterator() {} 798 799DictionaryValue* DictionaryValue::DeepCopy() const { 800 DictionaryValue* result = new DictionaryValue; 801 802 for (ValueMap::const_iterator current_entry(dictionary_.begin()); 803 current_entry != dictionary_.end(); ++current_entry) { 804 result->SetWithoutPathExpansion(current_entry->first, 805 current_entry->second->DeepCopy()); 806 } 807 808 return result; 809} 810 811scoped_ptr<DictionaryValue> DictionaryValue::CreateDeepCopy() const { 812 return make_scoped_ptr(DeepCopy()); 813} 814 815bool DictionaryValue::Equals(const Value* other) const { 816 if (other->GetType() != GetType()) 817 return false; 818 819 const DictionaryValue* other_dict = 820 static_cast<const DictionaryValue*>(other); 821 Iterator lhs_it(*this); 822 Iterator rhs_it(*other_dict); 823 while (!lhs_it.IsAtEnd() && !rhs_it.IsAtEnd()) { 824 if (lhs_it.key() != rhs_it.key() || 825 !lhs_it.value().Equals(&rhs_it.value())) { 826 return false; 827 } 828 lhs_it.Advance(); 829 rhs_it.Advance(); 830 } 831 if (!lhs_it.IsAtEnd() || !rhs_it.IsAtEnd()) 832 return false; 833 834 return true; 835} 836 837///////////////////// ListValue //////////////////// 838 839// static 840scoped_ptr<ListValue> ListValue::From(scoped_ptr<Value> value) { 841 ListValue* out; 842 if (value && value->GetAsList(&out)) { 843 ignore_result(value.release()); 844 return make_scoped_ptr(out); 845 } 846 return nullptr; 847} 848 849ListValue::ListValue() : Value(TYPE_LIST) { 850} 851 852ListValue::~ListValue() { 853 Clear(); 854} 855 856void ListValue::Clear() { 857 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) 858 delete *i; 859 list_.clear(); 860} 861 862bool ListValue::Set(size_t index, Value* in_value) { 863 if (!in_value) 864 return false; 865 866 if (index >= list_.size()) { 867 // Pad out any intermediate indexes with null settings 868 while (index > list_.size()) 869 Append(CreateNullValue()); 870 Append(in_value); 871 } else { 872 DCHECK(list_[index] != in_value); 873 delete list_[index]; 874 list_[index] = in_value; 875 } 876 return true; 877} 878 879bool ListValue::Set(size_t index, scoped_ptr<Value> in_value) { 880 return Set(index, in_value.release()); 881} 882 883bool ListValue::Get(size_t index, const Value** out_value) const { 884 if (index >= list_.size()) 885 return false; 886 887 if (out_value) 888 *out_value = list_[index]; 889 890 return true; 891} 892 893bool ListValue::Get(size_t index, Value** out_value) { 894 return static_cast<const ListValue&>(*this).Get( 895 index, 896 const_cast<const Value**>(out_value)); 897} 898 899bool ListValue::GetBoolean(size_t index, bool* bool_value) const { 900 const Value* value; 901 if (!Get(index, &value)) 902 return false; 903 904 return value->GetAsBoolean(bool_value); 905} 906 907bool ListValue::GetInteger(size_t index, int* out_value) const { 908 const Value* value; 909 if (!Get(index, &value)) 910 return false; 911 912 return value->GetAsInteger(out_value); 913} 914 915bool ListValue::GetDouble(size_t index, double* out_value) const { 916 const Value* value; 917 if (!Get(index, &value)) 918 return false; 919 920 return value->GetAsDouble(out_value); 921} 922 923bool ListValue::GetString(size_t index, std::string* out_value) const { 924 const Value* value; 925 if (!Get(index, &value)) 926 return false; 927 928 return value->GetAsString(out_value); 929} 930 931bool ListValue::GetBinary(size_t index, const BinaryValue** out_value) const { 932 const Value* value; 933 bool result = Get(index, &value); 934 if (!result || !value->IsType(TYPE_BINARY)) 935 return false; 936 937 if (out_value) 938 *out_value = static_cast<const BinaryValue*>(value); 939 940 return true; 941} 942 943bool ListValue::GetBinary(size_t index, BinaryValue** out_value) { 944 return static_cast<const ListValue&>(*this).GetBinary( 945 index, 946 const_cast<const BinaryValue**>(out_value)); 947} 948 949bool ListValue::GetDictionary(size_t index, 950 const DictionaryValue** out_value) const { 951 const Value* value; 952 bool result = Get(index, &value); 953 if (!result || !value->IsType(TYPE_DICTIONARY)) 954 return false; 955 956 if (out_value) 957 *out_value = static_cast<const DictionaryValue*>(value); 958 959 return true; 960} 961 962bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) { 963 return static_cast<const ListValue&>(*this).GetDictionary( 964 index, 965 const_cast<const DictionaryValue**>(out_value)); 966} 967 968bool ListValue::GetList(size_t index, const ListValue** out_value) const { 969 const Value* value; 970 bool result = Get(index, &value); 971 if (!result || !value->IsType(TYPE_LIST)) 972 return false; 973 974 if (out_value) 975 *out_value = static_cast<const ListValue*>(value); 976 977 return true; 978} 979 980bool ListValue::GetList(size_t index, ListValue** out_value) { 981 return static_cast<const ListValue&>(*this).GetList( 982 index, 983 const_cast<const ListValue**>(out_value)); 984} 985 986bool ListValue::Remove(size_t index, scoped_ptr<Value>* out_value) { 987 if (index >= list_.size()) 988 return false; 989 990 if (out_value) 991 out_value->reset(list_[index]); 992 else 993 delete list_[index]; 994 995 list_.erase(list_.begin() + index); 996 return true; 997} 998 999bool ListValue::Remove(const Value& value, size_t* index) { 1000 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) { 1001 if ((*i)->Equals(&value)) { 1002 size_t previous_index = i - list_.begin(); 1003 delete *i; 1004 list_.erase(i); 1005 1006 if (index) 1007 *index = previous_index; 1008 return true; 1009 } 1010 } 1011 return false; 1012} 1013 1014ListValue::iterator ListValue::Erase(iterator iter, 1015 scoped_ptr<Value>* out_value) { 1016 if (out_value) 1017 out_value->reset(*iter); 1018 else 1019 delete *iter; 1020 1021 return list_.erase(iter); 1022} 1023 1024void ListValue::Append(scoped_ptr<Value> in_value) { 1025 Append(in_value.release()); 1026} 1027 1028void ListValue::Append(Value* in_value) { 1029 DCHECK(in_value); 1030 list_.push_back(in_value); 1031} 1032 1033void ListValue::AppendBoolean(bool in_value) { 1034 Append(new FundamentalValue(in_value)); 1035} 1036 1037void ListValue::AppendInteger(int in_value) { 1038 Append(new FundamentalValue(in_value)); 1039} 1040 1041void ListValue::AppendDouble(double in_value) { 1042 Append(new FundamentalValue(in_value)); 1043} 1044 1045void ListValue::AppendString(const std::string& in_value) { 1046 Append(new StringValue(in_value)); 1047} 1048 1049void ListValue::AppendStrings(const std::vector<std::string>& in_values) { 1050 for (std::vector<std::string>::const_iterator it = in_values.begin(); 1051 it != in_values.end(); ++it) { 1052 AppendString(*it); 1053 } 1054} 1055 1056bool ListValue::AppendIfNotPresent(Value* in_value) { 1057 DCHECK(in_value); 1058 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) { 1059 if ((*i)->Equals(in_value)) { 1060 delete in_value; 1061 return false; 1062 } 1063 } 1064 list_.push_back(in_value); 1065 return true; 1066} 1067 1068bool ListValue::Insert(size_t index, Value* in_value) { 1069 DCHECK(in_value); 1070 if (index > list_.size()) 1071 return false; 1072 1073 list_.insert(list_.begin() + index, in_value); 1074 return true; 1075} 1076 1077ListValue::const_iterator ListValue::Find(const Value& value) const { 1078 return std::find_if(list_.begin(), list_.end(), ValueEquals(&value)); 1079} 1080 1081void ListValue::Swap(ListValue* other) { 1082 list_.swap(other->list_); 1083} 1084 1085bool ListValue::GetAsList(ListValue** out_value) { 1086 if (out_value) 1087 *out_value = this; 1088 return true; 1089} 1090 1091bool ListValue::GetAsList(const ListValue** out_value) const { 1092 if (out_value) 1093 *out_value = this; 1094 return true; 1095} 1096 1097ListValue* ListValue::DeepCopy() const { 1098 ListValue* result = new ListValue; 1099 1100 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) 1101 result->Append((*i)->DeepCopy()); 1102 1103 return result; 1104} 1105 1106scoped_ptr<ListValue> ListValue::CreateDeepCopy() const { 1107 return make_scoped_ptr(DeepCopy()); 1108} 1109 1110bool ListValue::Equals(const Value* other) const { 1111 if (other->GetType() != GetType()) 1112 return false; 1113 1114 const ListValue* other_list = 1115 static_cast<const ListValue*>(other); 1116 const_iterator lhs_it, rhs_it; 1117 for (lhs_it = begin(), rhs_it = other_list->begin(); 1118 lhs_it != end() && rhs_it != other_list->end(); 1119 ++lhs_it, ++rhs_it) { 1120 if (!(*lhs_it)->Equals(*rhs_it)) 1121 return false; 1122 } 1123 if (lhs_it != end() || rhs_it != other_list->end()) 1124 return false; 1125 1126 return true; 1127} 1128 1129std::ostream& operator<<(std::ostream& out, const Value& value) { 1130 std::string json; 1131 JSONWriter::WriteWithOptions(value, JSONWriter::OPTIONS_PRETTY_PRINT, &json); 1132 return out << json; 1133} 1134 1135} // namespace base 1136