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