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