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