values.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2010 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 "base/logging.h" 8#include "base/string_util.h" 9#include "base/utf_string_conversions.h" 10 11namespace { 12 13// Make a deep copy of |node|, but don't include empty lists or dictionaries 14// in the copy. It's possible for this function to return NULL and it 15// expects |node| to always be non-NULL. 16Value* CopyWithoutEmptyChildren(Value* node) { 17 DCHECK(node); 18 switch (node->GetType()) { 19 case Value::TYPE_LIST: { 20 ListValue* list = static_cast<ListValue*>(node); 21 ListValue* copy = new ListValue; 22 for (ListValue::const_iterator it = list->begin(); it != list->end(); 23 ++it) { 24 Value* child_copy = CopyWithoutEmptyChildren(*it); 25 if (child_copy) 26 copy->Append(child_copy); 27 } 28 if (!copy->empty()) 29 return copy; 30 31 delete copy; 32 return NULL; 33 } 34 35 case Value::TYPE_DICTIONARY: { 36 DictionaryValue* dict = static_cast<DictionaryValue*>(node); 37 DictionaryValue* copy = new DictionaryValue; 38 for (DictionaryValue::key_iterator it = dict->begin_keys(); 39 it != dict->end_keys(); ++it) { 40 Value* child = NULL; 41 bool rv = dict->GetWithoutPathExpansion(*it, &child); 42 DCHECK(rv); 43 Value* child_copy = CopyWithoutEmptyChildren(child); 44 if (child_copy) 45 copy->SetWithoutPathExpansion(*it, child_copy); 46 } 47 if (!copy->empty()) 48 return copy; 49 50 delete copy; 51 return NULL; 52 } 53 54 default: 55 // For everything else, just make a copy. 56 return node->DeepCopy(); 57 } 58} 59 60} // namespace 61 62///////////////////// Value //////////////////// 63 64Value::~Value() { 65} 66 67// static 68Value* Value::CreateNullValue() { 69 return new Value(TYPE_NULL); 70} 71 72// static 73Value* Value::CreateBooleanValue(bool in_value) { 74 return new FundamentalValue(in_value); 75} 76 77// static 78Value* Value::CreateIntegerValue(int in_value) { 79 return new FundamentalValue(in_value); 80} 81 82// static 83Value* Value::CreateRealValue(double in_value) { 84 return new FundamentalValue(in_value); 85} 86 87// static 88Value* Value::CreateStringValue(const std::string& in_value) { 89 return new StringValue(in_value); 90} 91 92// static 93Value* Value::CreateStringValue(const string16& in_value) { 94 return new StringValue(in_value); 95} 96 97// static 98BinaryValue* Value::CreateBinaryValue(char* buffer, size_t size) { 99 return BinaryValue::Create(buffer, size); 100} 101 102bool Value::GetAsBoolean(bool* out_value) const { 103 return false; 104} 105 106bool Value::GetAsInteger(int* out_value) const { 107 return false; 108} 109 110bool Value::GetAsReal(double* out_value) const { 111 return false; 112} 113 114bool Value::GetAsString(std::string* out_value) const { 115 return false; 116} 117 118bool Value::GetAsString(string16* out_value) const { 119 return false; 120} 121 122Value* Value::DeepCopy() const { 123 // This method should only be getting called for null Values--all subclasses 124 // need to provide their own implementation;. 125 DCHECK(IsType(TYPE_NULL)); 126 return CreateNullValue(); 127} 128 129bool Value::Equals(const Value* other) const { 130 // This method should only be getting called for null Values--all subclasses 131 // need to provide their own implementation;. 132 DCHECK(IsType(TYPE_NULL)); 133 return other->IsType(TYPE_NULL); 134} 135 136Value::Value(ValueType type) : type_(type) { 137} 138 139///////////////////// FundamentalValue //////////////////// 140 141FundamentalValue::FundamentalValue(bool in_value) 142 : Value(TYPE_BOOLEAN), boolean_value_(in_value) { 143} 144 145FundamentalValue::FundamentalValue(int in_value) 146 : Value(TYPE_INTEGER), integer_value_(in_value) { 147} 148 149FundamentalValue::FundamentalValue(double in_value) 150 : Value(TYPE_REAL), real_value_(in_value) { 151} 152 153FundamentalValue::~FundamentalValue() { 154} 155 156bool FundamentalValue::GetAsBoolean(bool* out_value) const { 157 if (out_value && IsType(TYPE_BOOLEAN)) 158 *out_value = boolean_value_; 159 return (IsType(TYPE_BOOLEAN)); 160} 161 162bool FundamentalValue::GetAsInteger(int* out_value) const { 163 if (out_value && IsType(TYPE_INTEGER)) 164 *out_value = integer_value_; 165 return (IsType(TYPE_INTEGER)); 166} 167 168bool FundamentalValue::GetAsReal(double* out_value) const { 169 if (out_value && IsType(TYPE_REAL)) 170 *out_value = real_value_; 171 return (IsType(TYPE_REAL)); 172} 173 174Value* FundamentalValue::DeepCopy() const { 175 switch (GetType()) { 176 case TYPE_BOOLEAN: 177 return CreateBooleanValue(boolean_value_); 178 179 case TYPE_INTEGER: 180 return CreateIntegerValue(integer_value_); 181 182 case TYPE_REAL: 183 return CreateRealValue(real_value_); 184 185 default: 186 NOTREACHED(); 187 return NULL; 188 } 189} 190 191bool FundamentalValue::Equals(const Value* other) const { 192 if (other->GetType() != GetType()) 193 return false; 194 195 switch (GetType()) { 196 case TYPE_BOOLEAN: { 197 bool lhs, rhs; 198 return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs; 199 } 200 case TYPE_INTEGER: { 201 int lhs, rhs; 202 return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs; 203 } 204 case TYPE_REAL: { 205 double lhs, rhs; 206 return GetAsReal(&lhs) && other->GetAsReal(&rhs) && lhs == rhs; 207 } 208 default: 209 NOTREACHED(); 210 return false; 211 } 212} 213 214///////////////////// StringValue //////////////////// 215 216StringValue::StringValue(const std::string& in_value) 217 : Value(TYPE_STRING), 218 value_(in_value) { 219 DCHECK(IsStringUTF8(in_value)); 220} 221 222StringValue::StringValue(const string16& in_value) 223 : Value(TYPE_STRING), 224 value_(UTF16ToUTF8(in_value)) { 225} 226 227StringValue::~StringValue() { 228} 229 230bool StringValue::GetAsString(std::string* out_value) const { 231 if (out_value) 232 *out_value = value_; 233 return true; 234} 235 236bool StringValue::GetAsString(string16* out_value) const { 237 if (out_value) 238 *out_value = UTF8ToUTF16(value_); 239 return true; 240} 241 242Value* StringValue::DeepCopy() const { 243 return CreateStringValue(value_); 244} 245 246bool StringValue::Equals(const Value* other) const { 247 if (other->GetType() != GetType()) 248 return false; 249 std::string lhs, rhs; 250 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs; 251} 252 253///////////////////// BinaryValue //////////////////// 254 255// static 256BinaryValue* BinaryValue::Create(char* buffer, size_t size) { 257 if (!buffer) 258 return NULL; 259 260 return new BinaryValue(buffer, size); 261} 262 263// static 264BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer, 265 size_t size) { 266 if (!buffer) 267 return NULL; 268 269 char* buffer_copy = new char[size]; 270 memcpy(buffer_copy, buffer, size); 271 return new BinaryValue(buffer_copy, size); 272} 273 274 275BinaryValue::BinaryValue(char* buffer, size_t size) 276 : Value(TYPE_BINARY), 277 buffer_(buffer), 278 size_(size) { 279 DCHECK(buffer_); 280} 281 282BinaryValue::~BinaryValue() { 283 DCHECK(buffer_); 284 if (buffer_) 285 delete[] buffer_; 286} 287 288Value* BinaryValue::DeepCopy() const { 289 return CreateWithCopiedBuffer(buffer_, size_); 290} 291 292bool BinaryValue::Equals(const Value* other) const { 293 if (other->GetType() != GetType()) 294 return false; 295 const BinaryValue* other_binary = static_cast<const BinaryValue*>(other); 296 if (other_binary->size_ != size_) 297 return false; 298 return !memcmp(buffer_, other_binary->buffer_, size_); 299} 300 301///////////////////// DictionaryValue //////////////////// 302 303DictionaryValue::DictionaryValue() 304 : Value(TYPE_DICTIONARY) { 305} 306 307DictionaryValue::~DictionaryValue() { 308 Clear(); 309} 310 311Value* DictionaryValue::DeepCopy() const { 312 DictionaryValue* result = new DictionaryValue; 313 314 for (ValueMap::const_iterator current_entry(dictionary_.begin()); 315 current_entry != dictionary_.end(); ++current_entry) { 316 result->SetWithoutPathExpansion(current_entry->first, 317 current_entry->second->DeepCopy()); 318 } 319 320 return result; 321} 322 323bool DictionaryValue::Equals(const Value* other) const { 324 if (other->GetType() != GetType()) 325 return false; 326 327 const DictionaryValue* other_dict = 328 static_cast<const DictionaryValue*>(other); 329 key_iterator lhs_it(begin_keys()); 330 key_iterator rhs_it(other_dict->begin_keys()); 331 while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) { 332 Value* lhs; 333 Value* rhs; 334 if (*lhs_it != *rhs_it || 335 !GetWithoutPathExpansion(*lhs_it, &lhs) || 336 !other_dict->GetWithoutPathExpansion(*rhs_it, &rhs) || 337 !lhs->Equals(rhs)) { 338 return false; 339 } 340 ++lhs_it; 341 ++rhs_it; 342 } 343 if (lhs_it != end_keys() || rhs_it != other_dict->end_keys()) 344 return false; 345 346 return true; 347} 348 349bool DictionaryValue::HasKey(const std::string& key) const { 350 DCHECK(IsStringUTF8(key)); 351 ValueMap::const_iterator current_entry = dictionary_.find(key); 352 DCHECK((current_entry == dictionary_.end()) || current_entry->second); 353 return current_entry != dictionary_.end(); 354} 355 356void DictionaryValue::Clear() { 357 ValueMap::iterator dict_iterator = dictionary_.begin(); 358 while (dict_iterator != dictionary_.end()) { 359 delete dict_iterator->second; 360 ++dict_iterator; 361 } 362 363 dictionary_.clear(); 364} 365 366void DictionaryValue::Set(const std::string& path, Value* in_value) { 367 DCHECK(IsStringUTF8(path)); 368 DCHECK(in_value); 369 370 std::string current_path(path); 371 DictionaryValue* current_dictionary = this; 372 for (size_t delimiter_position = current_path.find('.'); 373 delimiter_position != std::string::npos; 374 delimiter_position = current_path.find('.')) { 375 // Assume that we're indexing into a dictionary. 376 std::string key(current_path, 0, delimiter_position); 377 DictionaryValue* child_dictionary = NULL; 378 if (!current_dictionary->GetDictionary(key, &child_dictionary)) { 379 child_dictionary = new DictionaryValue; 380 current_dictionary->SetWithoutPathExpansion(key, child_dictionary); 381 } 382 383 current_dictionary = child_dictionary; 384 current_path.erase(0, delimiter_position + 1); 385 } 386 387 current_dictionary->SetWithoutPathExpansion(current_path, in_value); 388} 389 390void DictionaryValue::SetBoolean(const std::string& path, bool in_value) { 391 Set(path, CreateBooleanValue(in_value)); 392} 393 394void DictionaryValue::SetInteger(const std::string& path, int in_value) { 395 Set(path, CreateIntegerValue(in_value)); 396} 397 398void DictionaryValue::SetReal(const std::string& path, double in_value) { 399 Set(path, CreateRealValue(in_value)); 400} 401 402void DictionaryValue::SetString(const std::string& path, 403 const std::string& in_value) { 404 Set(path, CreateStringValue(in_value)); 405} 406 407void DictionaryValue::SetString(const std::string& path, 408 const string16& in_value) { 409 Set(path, CreateStringValue(in_value)); 410} 411 412void DictionaryValue::SetWithoutPathExpansion(const std::string& key, 413 Value* in_value) { 414 // If there's an existing value here, we need to delete it, because 415 // we own all our children. 416 if (HasKey(key)) { 417 DCHECK(dictionary_[key] != in_value); // This would be bogus 418 delete dictionary_[key]; 419 } 420 421 dictionary_[key] = in_value; 422} 423 424bool DictionaryValue::Get(const std::string& path, Value** out_value) const { 425 DCHECK(IsStringUTF8(path)); 426 std::string current_path(path); 427 const DictionaryValue* current_dictionary = this; 428 for (size_t delimiter_position = current_path.find('.'); 429 delimiter_position != std::string::npos; 430 delimiter_position = current_path.find('.')) { 431 DictionaryValue* child_dictionary = NULL; 432 if (!current_dictionary->GetDictionary( 433 current_path.substr(0, delimiter_position), &child_dictionary)) 434 return false; 435 436 current_dictionary = child_dictionary; 437 current_path.erase(0, delimiter_position + 1); 438 } 439 440 return current_dictionary->GetWithoutPathExpansion(current_path, out_value); 441} 442 443bool DictionaryValue::GetBoolean(const std::string& path, 444 bool* bool_value) const { 445 Value* value; 446 if (!Get(path, &value)) 447 return false; 448 449 return value->GetAsBoolean(bool_value); 450} 451 452bool DictionaryValue::GetInteger(const std::string& path, 453 int* out_value) const { 454 Value* value; 455 if (!Get(path, &value)) 456 return false; 457 458 return value->GetAsInteger(out_value); 459} 460 461bool DictionaryValue::GetReal(const std::string& path, 462 double* out_value) const { 463 Value* value; 464 if (!Get(path, &value)) 465 return false; 466 467 return value->GetAsReal(out_value); 468} 469 470bool DictionaryValue::GetString(const std::string& path, 471 std::string* out_value) const { 472 Value* value; 473 if (!Get(path, &value)) 474 return false; 475 476 return value->GetAsString(out_value); 477} 478 479bool DictionaryValue::GetString(const std::string& path, 480 string16* out_value) const { 481 Value* value; 482 if (!Get(path, &value)) 483 return false; 484 485 return value->GetAsString(out_value); 486} 487 488bool DictionaryValue::GetStringASCII(const std::string& path, 489 std::string* out_value) const { 490 std::string out; 491 if (!GetString(path, &out)) 492 return false; 493 494 if (!IsStringASCII(out)) { 495 NOTREACHED(); 496 return false; 497 } 498 499 out_value->assign(out); 500 return true; 501} 502 503bool DictionaryValue::GetBinary(const std::string& path, 504 BinaryValue** out_value) const { 505 Value* value; 506 bool result = Get(path, &value); 507 if (!result || !value->IsType(TYPE_BINARY)) 508 return false; 509 510 if (out_value) 511 *out_value = static_cast<BinaryValue*>(value); 512 513 return true; 514} 515 516bool DictionaryValue::GetDictionary(const std::string& path, 517 DictionaryValue** out_value) const { 518 Value* value; 519 bool result = Get(path, &value); 520 if (!result || !value->IsType(TYPE_DICTIONARY)) 521 return false; 522 523 if (out_value) 524 *out_value = static_cast<DictionaryValue*>(value); 525 526 return true; 527} 528 529bool DictionaryValue::GetList(const std::string& path, 530 ListValue** out_value) const { 531 Value* value; 532 bool result = Get(path, &value); 533 if (!result || !value->IsType(TYPE_LIST)) 534 return false; 535 536 if (out_value) 537 *out_value = static_cast<ListValue*>(value); 538 539 return true; 540} 541 542bool DictionaryValue::GetWithoutPathExpansion(const std::string& key, 543 Value** out_value) const { 544 DCHECK(IsStringUTF8(key)); 545 ValueMap::const_iterator entry_iterator = dictionary_.find(key); 546 if (entry_iterator == dictionary_.end()) 547 return false; 548 549 Value* entry = entry_iterator->second; 550 if (out_value) 551 *out_value = entry; 552 return true; 553} 554 555bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::string& key, 556 int* out_value) const { 557 Value* value; 558 if (!GetWithoutPathExpansion(key, &value)) 559 return false; 560 561 return value->GetAsInteger(out_value); 562} 563 564bool DictionaryValue::GetStringWithoutPathExpansion( 565 const std::string& key, 566 std::string* out_value) const { 567 Value* value; 568 if (!GetWithoutPathExpansion(key, &value)) 569 return false; 570 571 return value->GetAsString(out_value); 572} 573 574bool DictionaryValue::GetStringWithoutPathExpansion( 575 const std::string& key, 576 string16* out_value) const { 577 Value* value; 578 if (!GetWithoutPathExpansion(key, &value)) 579 return false; 580 581 return value->GetAsString(out_value); 582} 583 584bool DictionaryValue::GetDictionaryWithoutPathExpansion( 585 const std::string& key, 586 DictionaryValue** out_value) const { 587 Value* value; 588 bool result = GetWithoutPathExpansion(key, &value); 589 if (!result || !value->IsType(TYPE_DICTIONARY)) 590 return false; 591 592 if (out_value) 593 *out_value = static_cast<DictionaryValue*>(value); 594 595 return true; 596} 597 598bool DictionaryValue::GetListWithoutPathExpansion(const std::string& key, 599 ListValue** out_value) const { 600 Value* value; 601 bool result = GetWithoutPathExpansion(key, &value); 602 if (!result || !value->IsType(TYPE_LIST)) 603 return false; 604 605 if (out_value) 606 *out_value = static_cast<ListValue*>(value); 607 608 return true; 609} 610 611bool DictionaryValue::Remove(const std::string& path, Value** out_value) { 612 DCHECK(IsStringUTF8(path)); 613 std::string current_path(path); 614 DictionaryValue* current_dictionary = this; 615 size_t delimiter_position = current_path.rfind('.'); 616 if (delimiter_position != std::string::npos) { 617 if (!GetDictionary(current_path.substr(0, delimiter_position), 618 ¤t_dictionary)) 619 return false; 620 current_path.erase(0, delimiter_position + 1); 621 } 622 623 return current_dictionary->RemoveWithoutPathExpansion(current_path, 624 out_value); 625} 626 627bool DictionaryValue::RemoveWithoutPathExpansion(const std::string& key, 628 Value** out_value) { 629 DCHECK(IsStringUTF8(key)); 630 ValueMap::iterator entry_iterator = dictionary_.find(key); 631 if (entry_iterator == dictionary_.end()) 632 return false; 633 634 Value* entry = entry_iterator->second; 635 if (out_value) 636 *out_value = entry; 637 else 638 delete entry; 639 dictionary_.erase(entry_iterator); 640 return true; 641} 642 643DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() { 644 Value* copy = CopyWithoutEmptyChildren(this); 645 return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue; 646} 647 648void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) { 649 for (DictionaryValue::key_iterator key(dictionary->begin_keys()); 650 key != dictionary->end_keys(); ++key) { 651 Value* merge_value; 652 if (dictionary->GetWithoutPathExpansion(*key, &merge_value)) { 653 // Check whether we have to merge dictionaries. 654 if (merge_value->IsType(Value::TYPE_DICTIONARY)) { 655 DictionaryValue* sub_dict; 656 if (GetDictionaryWithoutPathExpansion(*key, &sub_dict)) { 657 sub_dict->MergeDictionary( 658 static_cast<const DictionaryValue*>(merge_value)); 659 continue; 660 } 661 } 662 // All other cases: Make a copy and hook it up. 663 SetWithoutPathExpansion(*key, merge_value->DeepCopy()); 664 } 665 } 666} 667 668bool DictionaryValue::GetDifferingPathsHelper( 669 const std::string& path_prefix, 670 const DictionaryValue* other, 671 std::vector<std::string>* different_paths) const { 672 bool added_path = false; 673 std::map<std::string, Value*>::const_iterator current_this; 674 std::map<std::string, Value*>::const_iterator end_this; 675 current_this = dictionary_.begin(); 676 end_this = dictionary_.end(); 677 if (!other) { 678 // Recursively add all paths from the |this| dictionary, since they are 679 // not in |other|. 680 for (; current_this != end_this; ++current_this) { 681 std::string full_path_for_key(path_prefix.empty() ? current_this->first : 682 path_prefix + "." + current_this->first); 683 different_paths->push_back(full_path_for_key); 684 added_path = true; 685 if (current_this->second->IsType(Value::TYPE_DICTIONARY)) { 686 const DictionaryValue* dictionary_this = 687 static_cast<const DictionaryValue*>(current_this->second); 688 dictionary_this->GetDifferingPathsHelper(full_path_for_key, 689 NULL, 690 different_paths); 691 } 692 } 693 } else { 694 // Both the |this| and |other| dictionaries have entries. Iterate over 695 // both simultaneously. Paths that are in one but not the other are 696 // added to |different_paths| and DictionaryValues are processed 697 // recursively. 698 std::map<std::string, Value*>::const_iterator current_other = 699 other->dictionary_.begin(); 700 std::map<std::string, Value*>::const_iterator end_other = 701 other->dictionary_.end(); 702 while (current_this != end_this || current_other != end_other) { 703 const Value* recursion_this = NULL; 704 const Value* recursion_other = NULL; 705 const std::string* key_name = NULL; 706 bool current_value_known_equal = false; 707 if (current_this == end_this || 708 (current_other != end_other && 709 (current_other->first < current_this->first))) { 710 key_name = ¤t_other->first; 711 if (current_other->second->IsType(Value::TYPE_DICTIONARY)) 712 recursion_this = current_other->second; 713 ++current_other; 714 } else { 715 key_name = ¤t_this->first; 716 if (current_other == end_other || 717 current_this->first < current_other->first) { 718 if (current_this->second->IsType(Value::TYPE_DICTIONARY)) 719 recursion_this = current_this->second; 720 ++current_this; 721 } else { 722 DCHECK(current_this->first == current_other->first); 723 if (current_this->second->IsType(Value::TYPE_DICTIONARY)) { 724 recursion_this = current_this->second; 725 if (current_other->second->IsType(Value::TYPE_DICTIONARY)) { 726 recursion_other = current_other->second; 727 } 728 } else { 729 if (current_other->second->IsType(Value::TYPE_DICTIONARY)) { 730 recursion_this = current_other->second; 731 } else { 732 current_value_known_equal = 733 current_this->second->Equals(current_other->second); 734 } 735 } 736 ++current_this; 737 ++current_other; 738 } 739 } 740 const std::string& full_path_for_key(path_prefix.empty() ? 741 *key_name : path_prefix + "." + *key_name); 742 if (!current_value_known_equal) 743 different_paths->push_back(full_path_for_key); 744 if (recursion_this) { 745 const DictionaryValue* dictionary_this = 746 static_cast<const DictionaryValue*>(recursion_this); 747 bool subtree_changed = dictionary_this->GetDifferingPathsHelper( 748 full_path_for_key, 749 static_cast<const DictionaryValue*>(recursion_other), 750 different_paths); 751 if (subtree_changed) { 752 added_path = true; 753 } else { 754 // In order to maintain lexicographical sorting order, directory 755 // paths are pushed "optimistically" assuming that their subtree will 756 // contain differences. If in retrospect there were no differences 757 // in the subtree, the assumption was false and the dictionary path 758 // must be removed. 759 different_paths->pop_back(); 760 } 761 } else { 762 added_path |= !current_value_known_equal; 763 } 764 } 765 } 766 return added_path; 767} 768 769void DictionaryValue::GetDifferingPaths( 770 const DictionaryValue* other, 771 std::vector<std::string>* different_paths) const { 772 different_paths->clear(); 773 GetDifferingPathsHelper("", other, different_paths); 774} 775 776///////////////////// ListValue //////////////////// 777 778ListValue::ListValue() : Value(TYPE_LIST) { 779} 780 781ListValue::~ListValue() { 782 Clear(); 783} 784 785void ListValue::Clear() { 786 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) 787 delete *i; 788 list_.clear(); 789} 790 791bool ListValue::Set(size_t index, Value* in_value) { 792 if (!in_value) 793 return false; 794 795 if (index >= list_.size()) { 796 // Pad out any intermediate indexes with null settings 797 while (index > list_.size()) 798 Append(CreateNullValue()); 799 Append(in_value); 800 } else { 801 DCHECK(list_[index] != in_value); 802 delete list_[index]; 803 list_[index] = in_value; 804 } 805 return true; 806} 807 808bool ListValue::Get(size_t index, Value** out_value) const { 809 if (index >= list_.size()) 810 return false; 811 812 if (out_value) 813 *out_value = list_[index]; 814 815 return true; 816} 817 818bool ListValue::GetBoolean(size_t index, bool* bool_value) const { 819 Value* value; 820 if (!Get(index, &value)) 821 return false; 822 823 return value->GetAsBoolean(bool_value); 824} 825 826bool ListValue::GetInteger(size_t index, int* out_value) const { 827 Value* value; 828 if (!Get(index, &value)) 829 return false; 830 831 return value->GetAsInteger(out_value); 832} 833 834bool ListValue::GetReal(size_t index, double* out_value) const { 835 Value* value; 836 if (!Get(index, &value)) 837 return false; 838 839 return value->GetAsReal(out_value); 840} 841 842bool ListValue::GetString(size_t index, std::string* out_value) const { 843 Value* value; 844 if (!Get(index, &value)) 845 return false; 846 847 return value->GetAsString(out_value); 848} 849 850bool ListValue::GetString(size_t index, string16* out_value) const { 851 Value* value; 852 if (!Get(index, &value)) 853 return false; 854 855 return value->GetAsString(out_value); 856} 857 858bool ListValue::GetBinary(size_t index, BinaryValue** out_value) const { 859 Value* value; 860 bool result = Get(index, &value); 861 if (!result || !value->IsType(TYPE_BINARY)) 862 return false; 863 864 if (out_value) 865 *out_value = static_cast<BinaryValue*>(value); 866 867 return true; 868} 869 870bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) const { 871 Value* value; 872 bool result = Get(index, &value); 873 if (!result || !value->IsType(TYPE_DICTIONARY)) 874 return false; 875 876 if (out_value) 877 *out_value = static_cast<DictionaryValue*>(value); 878 879 return true; 880} 881 882bool ListValue::GetList(size_t index, ListValue** out_value) const { 883 Value* value; 884 bool result = Get(index, &value); 885 if (!result || !value->IsType(TYPE_LIST)) 886 return false; 887 888 if (out_value) 889 *out_value = static_cast<ListValue*>(value); 890 891 return true; 892} 893 894bool ListValue::Remove(size_t index, Value** out_value) { 895 if (index >= list_.size()) 896 return false; 897 898 if (out_value) 899 *out_value = list_[index]; 900 else 901 delete list_[index]; 902 903 list_.erase(list_.begin() + index); 904 return true; 905} 906 907int ListValue::Remove(const Value& value) { 908 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) { 909 if ((*i)->Equals(&value)) { 910 size_t index = i - list_.begin(); 911 delete *i; 912 list_.erase(i); 913 914 // TODO(anyone): Returning a signed int type here is just wrong. 915 // Change this interface to return a size_t. 916 DCHECK(index <= INT_MAX); 917 int return_index = static_cast<int>(index); 918 return return_index; 919 } 920 } 921 return -1; 922} 923 924void ListValue::Append(Value* in_value) { 925 DCHECK(in_value); 926 list_.push_back(in_value); 927} 928 929bool ListValue::AppendIfNotPresent(Value* in_value) { 930 DCHECK(in_value); 931 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) { 932 if ((*i)->Equals(in_value)) 933 return false; 934 } 935 list_.push_back(in_value); 936 return true; 937} 938 939bool ListValue::Insert(size_t index, Value* in_value) { 940 DCHECK(in_value); 941 if (index > list_.size()) 942 return false; 943 944 list_.insert(list_.begin() + index, in_value); 945 return true; 946} 947 948Value* ListValue::DeepCopy() const { 949 ListValue* result = new ListValue; 950 951 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) 952 result->Append((*i)->DeepCopy()); 953 954 return result; 955} 956 957bool ListValue::Equals(const Value* other) const { 958 if (other->GetType() != GetType()) 959 return false; 960 961 const ListValue* other_list = 962 static_cast<const ListValue*>(other); 963 const_iterator lhs_it, rhs_it; 964 for (lhs_it = begin(), rhs_it = other_list->begin(); 965 lhs_it != end() && rhs_it != other_list->end(); 966 ++lhs_it, ++rhs_it) { 967 if (!(*lhs_it)->Equals(*rhs_it)) 968 return false; 969 } 970 if (lhs_it != end() || rhs_it != other_list->end()) 971 return false; 972 973 return true; 974} 975 976ValueSerializer::~ValueSerializer() { 977} 978