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 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 73FundamentalValue* Value::CreateBooleanValue(bool in_value) { 74 return new FundamentalValue(in_value); 75} 76 77// static 78FundamentalValue* Value::CreateIntegerValue(int in_value) { 79 return new FundamentalValue(in_value); 80} 81 82// static 83FundamentalValue* Value::CreateDoubleValue(double in_value) { 84 return new FundamentalValue(in_value); 85} 86 87// static 88StringValue* Value::CreateStringValue(const std::string& in_value) { 89 return new StringValue(in_value); 90} 91 92// static 93StringValue* 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::GetAsDouble(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_DOUBLE), double_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::GetAsDouble(double* out_value) const { 180 if (out_value && IsType(TYPE_DOUBLE)) 181 *out_value = double_value_; 182 return (IsType(TYPE_DOUBLE)); 183} 184 185FundamentalValue* 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 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_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 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 253StringValue* 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 266BinaryValue::~BinaryValue() { 267 DCHECK(buffer_); 268 if (buffer_) 269 delete[] buffer_; 270} 271 272// static 273BinaryValue* BinaryValue::Create(char* buffer, size_t size) { 274 if (!buffer) 275 return NULL; 276 277 return new BinaryValue(buffer, size); 278} 279 280// static 281BinaryValue* 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 291BinaryValue* BinaryValue::DeepCopy() const { 292 return CreateWithCopiedBuffer(buffer_, size_); 293} 294 295bool 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 304BinaryValue::BinaryValue(char* buffer, size_t size) 305 : Value(TYPE_BINARY), 306 buffer_(buffer), 307 size_(size) { 308 DCHECK(buffer_); 309} 310 311///////////////////// DictionaryValue //////////////////// 312 313DictionaryValue::DictionaryValue() 314 : Value(TYPE_DICTIONARY) { 315} 316 317DictionaryValue::~DictionaryValue() { 318 Clear(); 319} 320 321bool 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 328void 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 338void 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 362void DictionaryValue::SetBoolean(const std::string& path, bool in_value) { 363 Set(path, CreateBooleanValue(in_value)); 364} 365 366void DictionaryValue::SetInteger(const std::string& path, int in_value) { 367 Set(path, CreateIntegerValue(in_value)); 368} 369 370void DictionaryValue::SetDouble(const std::string& path, double in_value) { 371 Set(path, CreateDoubleValue(in_value)); 372} 373 374void DictionaryValue::SetString(const std::string& path, 375 const std::string& in_value) { 376 Set(path, CreateStringValue(in_value)); 377} 378 379void DictionaryValue::SetString(const std::string& path, 380 const string16& in_value) { 381 Set(path, CreateStringValue(in_value)); 382} 383 384void 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 396bool 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 415bool 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 424bool 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 433bool 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 442bool 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 451bool 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 460bool 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 475bool 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 488bool 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 501bool 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 514bool 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 527bool 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 536bool 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 545bool 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 555bool 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 565bool 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 579bool 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 592bool 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 608bool 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 624DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() { 625 Value* copy = CopyWithoutEmptyChildren(this); 626 return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue; 627} 628 629void 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 649DictionaryValue* 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 661bool 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 689ListValue::ListValue() : Value(TYPE_LIST) { 690} 691 692ListValue::~ListValue() { 693 Clear(); 694} 695 696void ListValue::Clear() { 697 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) 698 delete *i; 699 list_.clear(); 700} 701 702bool 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 719bool 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 729bool 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 737bool 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 745bool 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 753bool 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 761bool 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 769bool 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 781bool 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 793bool 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 805bool 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 818int 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 835void ListValue::Append(Value* in_value) { 836 DCHECK(in_value); 837 list_.push_back(in_value); 838} 839 840bool 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 852bool 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 861bool ListValue::GetAsList(ListValue** out_value) { 862 if (out_value) 863 *out_value = this; 864 return true; 865} 866 867ListValue* 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 876bool 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 895ValueSerializer::~ValueSerializer() { 896} 897