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