WebKit roll 98705:98715
[chromium-blink-merge.git] / base / values.cc
blob4719741a12cccabbb05e3af138baa01167ee8b3a
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.
5 #include "base/values.h"
7 #include <algorithm>
9 #include "base/float_util.h"
10 #include "base/logging.h"
11 #include "base/string_util.h"
12 #include "base/utf_string_conversions.h"
14 namespace {
16 // Make a deep copy of |node|, but don't include empty lists or dictionaries
17 // in the copy. It's possible for this function to return NULL and it
18 // expects |node| to always be non-NULL.
19 Value* CopyWithoutEmptyChildren(Value* node) {
20 DCHECK(node);
21 switch (node->GetType()) {
22 case Value::TYPE_LIST: {
23 ListValue* list = static_cast<ListValue*>(node);
24 ListValue* copy = new ListValue;
25 for (ListValue::const_iterator it = list->begin(); it != list->end();
26 ++it) {
27 Value* child_copy = CopyWithoutEmptyChildren(*it);
28 if (child_copy)
29 copy->Append(child_copy);
31 if (!copy->empty())
32 return copy;
34 delete copy;
35 return NULL;
38 case Value::TYPE_DICTIONARY: {
39 DictionaryValue* dict = static_cast<DictionaryValue*>(node);
40 DictionaryValue* copy = new DictionaryValue;
41 for (DictionaryValue::key_iterator it = dict->begin_keys();
42 it != dict->end_keys(); ++it) {
43 Value* child = NULL;
44 bool rv = dict->GetWithoutPathExpansion(*it, &child);
45 DCHECK(rv);
46 Value* child_copy = CopyWithoutEmptyChildren(child);
47 if (child_copy)
48 copy->SetWithoutPathExpansion(*it, child_copy);
50 if (!copy->empty())
51 return copy;
53 delete copy;
54 return NULL;
57 default:
58 // For everything else, just make a copy.
59 return node->DeepCopy();
63 // A small functor for comparing Values for std::find_if and similar.
64 class ValueEquals {
65 public:
66 // Pass the value against which all consecutive calls of the () operator will
67 // compare their argument to. This Value object must not be destroyed while
68 // the ValueEquals is in use.
69 ValueEquals(const Value* first) : first_(first) { }
71 bool operator ()(const Value* second) const {
72 return first_->Equals(second);
75 private:
76 const Value* first_;
79 } // namespace
81 namespace base {
83 ///////////////////// Value ////////////////////
85 Value::~Value() {
88 // static
89 Value* Value::CreateNullValue() {
90 return new Value(TYPE_NULL);
93 // static
94 FundamentalValue* Value::CreateBooleanValue(bool in_value) {
95 return new FundamentalValue(in_value);
98 // static
99 FundamentalValue* Value::CreateIntegerValue(int in_value) {
100 return new FundamentalValue(in_value);
103 // static
104 FundamentalValue* Value::CreateDoubleValue(double in_value) {
105 return new FundamentalValue(in_value);
108 // static
109 StringValue* Value::CreateStringValue(const std::string& in_value) {
110 return new StringValue(in_value);
113 // static
114 StringValue* Value::CreateStringValue(const string16& in_value) {
115 return new StringValue(in_value);
118 bool Value::GetAsBoolean(bool* out_value) const {
119 return false;
122 bool Value::GetAsInteger(int* out_value) const {
123 return false;
126 bool Value::GetAsDouble(double* out_value) const {
127 return false;
130 bool Value::GetAsString(std::string* out_value) const {
131 return false;
134 bool Value::GetAsString(string16* out_value) const {
135 return false;
138 bool Value::GetAsList(ListValue** out_value) {
139 return false;
142 bool Value::GetAsList(const ListValue** out_value) const {
143 return false;
146 Value* Value::DeepCopy() const {
147 // This method should only be getting called for null Values--all subclasses
148 // need to provide their own implementation;.
149 DCHECK(IsType(TYPE_NULL));
150 return CreateNullValue();
153 bool Value::Equals(const Value* other) const {
154 // This method should only be getting called for null Values--all subclasses
155 // need to provide their own implementation;.
156 DCHECK(IsType(TYPE_NULL));
157 return other->IsType(TYPE_NULL);
160 // static
161 bool Value::Equals(const Value* a, const Value* b) {
162 if ((a == NULL) && (b == NULL)) return true;
163 if ((a == NULL) ^ (b == NULL)) return false;
164 return a->Equals(b);
167 Value::Value(Type type) : type_(type) {
170 ///////////////////// FundamentalValue ////////////////////
172 FundamentalValue::FundamentalValue(bool in_value)
173 : Value(TYPE_BOOLEAN), boolean_value_(in_value) {
176 FundamentalValue::FundamentalValue(int in_value)
177 : Value(TYPE_INTEGER), integer_value_(in_value) {
180 FundamentalValue::FundamentalValue(double in_value)
181 : Value(TYPE_DOUBLE), double_value_(in_value) {
182 if (!IsFinite(double_value_)) {
183 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
184 << "values cannot be represented in JSON";
185 double_value_ = 0.0;
189 FundamentalValue::~FundamentalValue() {
192 bool FundamentalValue::GetAsBoolean(bool* out_value) const {
193 if (out_value && IsType(TYPE_BOOLEAN))
194 *out_value = boolean_value_;
195 return (IsType(TYPE_BOOLEAN));
198 bool FundamentalValue::GetAsInteger(int* out_value) const {
199 if (out_value && IsType(TYPE_INTEGER))
200 *out_value = integer_value_;
201 return (IsType(TYPE_INTEGER));
204 bool FundamentalValue::GetAsDouble(double* out_value) const {
205 if (out_value && IsType(TYPE_DOUBLE))
206 *out_value = double_value_;
207 else if (out_value && IsType(TYPE_INTEGER))
208 *out_value = integer_value_;
209 return (IsType(TYPE_DOUBLE) || IsType(TYPE_INTEGER));
212 FundamentalValue* FundamentalValue::DeepCopy() const {
213 switch (GetType()) {
214 case TYPE_BOOLEAN:
215 return CreateBooleanValue(boolean_value_);
217 case TYPE_INTEGER:
218 return CreateIntegerValue(integer_value_);
220 case TYPE_DOUBLE:
221 return CreateDoubleValue(double_value_);
223 default:
224 NOTREACHED();
225 return NULL;
229 bool FundamentalValue::Equals(const Value* other) const {
230 if (other->GetType() != GetType())
231 return false;
233 switch (GetType()) {
234 case TYPE_BOOLEAN: {
235 bool lhs, rhs;
236 return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs;
238 case TYPE_INTEGER: {
239 int lhs, rhs;
240 return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs;
242 case TYPE_DOUBLE: {
243 double lhs, rhs;
244 return GetAsDouble(&lhs) && other->GetAsDouble(&rhs) && lhs == rhs;
246 default:
247 NOTREACHED();
248 return false;
252 ///////////////////// StringValue ////////////////////
254 StringValue::StringValue(const std::string& in_value)
255 : Value(TYPE_STRING),
256 value_(in_value) {
257 DCHECK(IsStringUTF8(in_value));
260 StringValue::StringValue(const string16& in_value)
261 : Value(TYPE_STRING),
262 value_(UTF16ToUTF8(in_value)) {
265 StringValue::~StringValue() {
268 bool StringValue::GetAsString(std::string* out_value) const {
269 if (out_value)
270 *out_value = value_;
271 return true;
274 bool StringValue::GetAsString(string16* out_value) const {
275 if (out_value)
276 *out_value = UTF8ToUTF16(value_);
277 return true;
280 StringValue* StringValue::DeepCopy() const {
281 return CreateStringValue(value_);
284 bool StringValue::Equals(const Value* other) const {
285 if (other->GetType() != GetType())
286 return false;
287 std::string lhs, rhs;
288 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
291 ///////////////////// BinaryValue ////////////////////
293 BinaryValue::~BinaryValue() {
294 DCHECK(buffer_);
295 if (buffer_)
296 delete[] buffer_;
299 // static
300 BinaryValue* BinaryValue::Create(char* buffer, size_t size) {
301 if (!buffer)
302 return NULL;
304 return new BinaryValue(buffer, size);
307 // static
308 BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
309 size_t size) {
310 if (!buffer)
311 return NULL;
313 char* buffer_copy = new char[size];
314 memcpy(buffer_copy, buffer, size);
315 return new BinaryValue(buffer_copy, size);
318 BinaryValue* BinaryValue::DeepCopy() const {
319 return CreateWithCopiedBuffer(buffer_, size_);
322 bool BinaryValue::Equals(const Value* other) const {
323 if (other->GetType() != GetType())
324 return false;
325 const BinaryValue* other_binary = static_cast<const BinaryValue*>(other);
326 if (other_binary->size_ != size_)
327 return false;
328 return !memcmp(buffer_, other_binary->buffer_, size_);
331 BinaryValue::BinaryValue(char* buffer, size_t size)
332 : Value(TYPE_BINARY),
333 buffer_(buffer),
334 size_(size) {
335 DCHECK(buffer_);
338 ///////////////////// DictionaryValue ////////////////////
340 DictionaryValue::DictionaryValue()
341 : Value(TYPE_DICTIONARY) {
344 DictionaryValue::~DictionaryValue() {
345 Clear();
348 bool DictionaryValue::HasKey(const std::string& key) const {
349 DCHECK(IsStringUTF8(key));
350 ValueMap::const_iterator current_entry = dictionary_.find(key);
351 DCHECK((current_entry == dictionary_.end()) || current_entry->second);
352 return current_entry != dictionary_.end();
355 void DictionaryValue::Clear() {
356 ValueMap::iterator dict_iterator = dictionary_.begin();
357 while (dict_iterator != dictionary_.end()) {
358 delete dict_iterator->second;
359 ++dict_iterator;
362 dictionary_.clear();
365 void DictionaryValue::Set(const std::string& path, Value* in_value) {
366 DCHECK(IsStringUTF8(path));
367 DCHECK(in_value);
369 std::string current_path(path);
370 DictionaryValue* current_dictionary = this;
371 for (size_t delimiter_position = current_path.find('.');
372 delimiter_position != std::string::npos;
373 delimiter_position = current_path.find('.')) {
374 // Assume that we're indexing into a dictionary.
375 std::string key(current_path, 0, delimiter_position);
376 DictionaryValue* child_dictionary = NULL;
377 if (!current_dictionary->GetDictionary(key, &child_dictionary)) {
378 child_dictionary = new DictionaryValue;
379 current_dictionary->SetWithoutPathExpansion(key, child_dictionary);
382 current_dictionary = child_dictionary;
383 current_path.erase(0, delimiter_position + 1);
386 current_dictionary->SetWithoutPathExpansion(current_path, in_value);
389 void DictionaryValue::SetBoolean(const std::string& path, bool in_value) {
390 Set(path, CreateBooleanValue(in_value));
393 void DictionaryValue::SetInteger(const std::string& path, int in_value) {
394 Set(path, CreateIntegerValue(in_value));
397 void DictionaryValue::SetDouble(const std::string& path, double in_value) {
398 Set(path, CreateDoubleValue(in_value));
401 void DictionaryValue::SetString(const std::string& path,
402 const std::string& in_value) {
403 Set(path, CreateStringValue(in_value));
406 void DictionaryValue::SetString(const std::string& path,
407 const string16& in_value) {
408 Set(path, CreateStringValue(in_value));
411 void DictionaryValue::SetWithoutPathExpansion(const std::string& key,
412 Value* in_value) {
413 // If there's an existing value here, we need to delete it, because
414 // we own all our children.
415 std::pair<ValueMap::iterator, bool> ins_res =
416 dictionary_.insert(std::make_pair(key, in_value));
417 if (!ins_res.second) {
418 DCHECK_NE(ins_res.first->second, in_value); // This would be bogus
419 delete ins_res.first->second;
420 ins_res.first->second = in_value;
424 bool DictionaryValue::Get(const std::string& path, Value** out_value) const {
425 DCHECK(IsStringUTF8(path));
426 std::string current_path(path);
427 const DictionaryValue* current_dictionary = this;
428 for (size_t delimiter_position = current_path.find('.');
429 delimiter_position != std::string::npos;
430 delimiter_position = current_path.find('.')) {
431 DictionaryValue* child_dictionary = NULL;
432 if (!current_dictionary->GetDictionary(
433 current_path.substr(0, delimiter_position), &child_dictionary))
434 return false;
436 current_dictionary = child_dictionary;
437 current_path.erase(0, delimiter_position + 1);
440 return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
443 bool DictionaryValue::GetBoolean(const std::string& path,
444 bool* bool_value) const {
445 Value* value;
446 if (!Get(path, &value))
447 return false;
449 return value->GetAsBoolean(bool_value);
452 bool DictionaryValue::GetInteger(const std::string& path,
453 int* out_value) const {
454 Value* value;
455 if (!Get(path, &value))
456 return false;
458 return value->GetAsInteger(out_value);
461 bool DictionaryValue::GetDouble(const std::string& path,
462 double* out_value) const {
463 Value* value;
464 if (!Get(path, &value))
465 return false;
467 return value->GetAsDouble(out_value);
470 bool DictionaryValue::GetString(const std::string& path,
471 std::string* out_value) const {
472 Value* value;
473 if (!Get(path, &value))
474 return false;
476 return value->GetAsString(out_value);
479 bool DictionaryValue::GetString(const std::string& path,
480 string16* out_value) const {
481 Value* value;
482 if (!Get(path, &value))
483 return false;
485 return value->GetAsString(out_value);
488 bool DictionaryValue::GetStringASCII(const std::string& path,
489 std::string* out_value) const {
490 std::string out;
491 if (!GetString(path, &out))
492 return false;
494 if (!IsStringASCII(out)) {
495 NOTREACHED();
496 return false;
499 out_value->assign(out);
500 return true;
503 bool DictionaryValue::GetBinary(const std::string& path,
504 BinaryValue** out_value) const {
505 Value* value;
506 bool result = Get(path, &value);
507 if (!result || !value->IsType(TYPE_BINARY))
508 return false;
510 if (out_value)
511 *out_value = static_cast<BinaryValue*>(value);
513 return true;
516 bool DictionaryValue::GetDictionary(const std::string& path,
517 DictionaryValue** out_value) const {
518 Value* value;
519 bool result = Get(path, &value);
520 if (!result || !value->IsType(TYPE_DICTIONARY))
521 return false;
523 if (out_value)
524 *out_value = static_cast<DictionaryValue*>(value);
526 return true;
529 bool DictionaryValue::GetList(const std::string& path,
530 ListValue** out_value) const {
531 Value* value;
532 bool result = Get(path, &value);
533 if (!result || !value->IsType(TYPE_LIST))
534 return false;
536 if (out_value)
537 *out_value = static_cast<ListValue*>(value);
539 return true;
542 bool DictionaryValue::GetWithoutPathExpansion(const std::string& key,
543 Value** out_value) const {
544 DCHECK(IsStringUTF8(key));
545 ValueMap::const_iterator entry_iterator = dictionary_.find(key);
546 if (entry_iterator == dictionary_.end())
547 return false;
549 Value* entry = entry_iterator->second;
550 if (out_value)
551 *out_value = entry;
552 return true;
555 bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::string& key,
556 int* out_value) const {
557 Value* value;
558 if (!GetWithoutPathExpansion(key, &value))
559 return false;
561 return value->GetAsInteger(out_value);
564 bool DictionaryValue::GetDoubleWithoutPathExpansion(const std::string& key,
565 double* out_value) const {
566 Value* value;
567 if (!GetWithoutPathExpansion(key, &value))
568 return false;
570 return value->GetAsDouble(out_value);
573 bool DictionaryValue::GetStringWithoutPathExpansion(
574 const std::string& key,
575 std::string* out_value) const {
576 Value* value;
577 if (!GetWithoutPathExpansion(key, &value))
578 return false;
580 return value->GetAsString(out_value);
583 bool DictionaryValue::GetStringWithoutPathExpansion(
584 const std::string& key,
585 string16* out_value) const {
586 Value* value;
587 if (!GetWithoutPathExpansion(key, &value))
588 return false;
590 return value->GetAsString(out_value);
593 bool DictionaryValue::GetDictionaryWithoutPathExpansion(
594 const std::string& key,
595 DictionaryValue** out_value) const {
596 Value* value;
597 bool result = GetWithoutPathExpansion(key, &value);
598 if (!result || !value->IsType(TYPE_DICTIONARY))
599 return false;
601 if (out_value)
602 *out_value = static_cast<DictionaryValue*>(value);
604 return true;
607 bool DictionaryValue::GetListWithoutPathExpansion(const std::string& key,
608 ListValue** out_value) const {
609 Value* value;
610 bool result = GetWithoutPathExpansion(key, &value);
611 if (!result || !value->IsType(TYPE_LIST))
612 return false;
614 if (out_value)
615 *out_value = static_cast<ListValue*>(value);
617 return true;
620 bool DictionaryValue::Remove(const std::string& path, Value** out_value) {
621 DCHECK(IsStringUTF8(path));
622 std::string current_path(path);
623 DictionaryValue* current_dictionary = this;
624 size_t delimiter_position = current_path.rfind('.');
625 if (delimiter_position != std::string::npos) {
626 if (!GetDictionary(current_path.substr(0, delimiter_position),
627 &current_dictionary))
628 return false;
629 current_path.erase(0, delimiter_position + 1);
632 return current_dictionary->RemoveWithoutPathExpansion(current_path,
633 out_value);
636 bool DictionaryValue::RemoveWithoutPathExpansion(const std::string& key,
637 Value** out_value) {
638 DCHECK(IsStringUTF8(key));
639 ValueMap::iterator entry_iterator = dictionary_.find(key);
640 if (entry_iterator == dictionary_.end())
641 return false;
643 Value* entry = entry_iterator->second;
644 if (out_value)
645 *out_value = entry;
646 else
647 delete entry;
648 dictionary_.erase(entry_iterator);
649 return true;
652 DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() {
653 Value* copy = CopyWithoutEmptyChildren(this);
654 return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue;
657 void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
658 for (DictionaryValue::key_iterator key(dictionary->begin_keys());
659 key != dictionary->end_keys(); ++key) {
660 Value* merge_value;
661 if (dictionary->GetWithoutPathExpansion(*key, &merge_value)) {
662 // Check whether we have to merge dictionaries.
663 if (merge_value->IsType(Value::TYPE_DICTIONARY)) {
664 DictionaryValue* sub_dict;
665 if (GetDictionaryWithoutPathExpansion(*key, &sub_dict)) {
666 sub_dict->MergeDictionary(
667 static_cast<const DictionaryValue*>(merge_value));
668 continue;
671 // All other cases: Make a copy and hook it up.
672 SetWithoutPathExpansion(*key, merge_value->DeepCopy());
677 DictionaryValue* DictionaryValue::DeepCopy() const {
678 DictionaryValue* result = new DictionaryValue;
680 for (ValueMap::const_iterator current_entry(dictionary_.begin());
681 current_entry != dictionary_.end(); ++current_entry) {
682 result->SetWithoutPathExpansion(current_entry->first,
683 current_entry->second->DeepCopy());
686 return result;
689 bool DictionaryValue::Equals(const Value* other) const {
690 if (other->GetType() != GetType())
691 return false;
693 const DictionaryValue* other_dict =
694 static_cast<const DictionaryValue*>(other);
695 key_iterator lhs_it(begin_keys());
696 key_iterator rhs_it(other_dict->begin_keys());
697 while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) {
698 Value* lhs;
699 Value* rhs;
700 if (*lhs_it != *rhs_it ||
701 !GetWithoutPathExpansion(*lhs_it, &lhs) ||
702 !other_dict->GetWithoutPathExpansion(*rhs_it, &rhs) ||
703 !lhs->Equals(rhs)) {
704 return false;
706 ++lhs_it;
707 ++rhs_it;
709 if (lhs_it != end_keys() || rhs_it != other_dict->end_keys())
710 return false;
712 return true;
715 ///////////////////// ListValue ////////////////////
717 ListValue::ListValue() : Value(TYPE_LIST) {
720 ListValue::~ListValue() {
721 Clear();
724 void ListValue::Clear() {
725 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
726 delete *i;
727 list_.clear();
730 bool ListValue::Set(size_t index, Value* in_value) {
731 if (!in_value)
732 return false;
734 if (index >= list_.size()) {
735 // Pad out any intermediate indexes with null settings
736 while (index > list_.size())
737 Append(CreateNullValue());
738 Append(in_value);
739 } else {
740 DCHECK(list_[index] != in_value);
741 delete list_[index];
742 list_[index] = in_value;
744 return true;
747 bool ListValue::Get(size_t index, Value** out_value) const {
748 if (index >= list_.size())
749 return false;
751 if (out_value)
752 *out_value = list_[index];
754 return true;
757 bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
758 Value* value;
759 if (!Get(index, &value))
760 return false;
762 return value->GetAsBoolean(bool_value);
765 bool ListValue::GetInteger(size_t index, int* out_value) const {
766 Value* value;
767 if (!Get(index, &value))
768 return false;
770 return value->GetAsInteger(out_value);
773 bool ListValue::GetDouble(size_t index, double* out_value) const {
774 Value* value;
775 if (!Get(index, &value))
776 return false;
778 return value->GetAsDouble(out_value);
781 bool ListValue::GetString(size_t index, std::string* out_value) const {
782 Value* value;
783 if (!Get(index, &value))
784 return false;
786 return value->GetAsString(out_value);
789 bool ListValue::GetString(size_t index, string16* out_value) const {
790 Value* value;
791 if (!Get(index, &value))
792 return false;
794 return value->GetAsString(out_value);
797 bool ListValue::GetBinary(size_t index, BinaryValue** out_value) const {
798 Value* value;
799 bool result = Get(index, &value);
800 if (!result || !value->IsType(TYPE_BINARY))
801 return false;
803 if (out_value)
804 *out_value = static_cast<BinaryValue*>(value);
806 return true;
809 bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) const {
810 Value* value;
811 bool result = Get(index, &value);
812 if (!result || !value->IsType(TYPE_DICTIONARY))
813 return false;
815 if (out_value)
816 *out_value = static_cast<DictionaryValue*>(value);
818 return true;
821 bool ListValue::GetList(size_t index, ListValue** out_value) const {
822 Value* value;
823 bool result = Get(index, &value);
824 if (!result || !value->IsType(TYPE_LIST))
825 return false;
827 if (out_value)
828 *out_value = static_cast<ListValue*>(value);
830 return true;
833 bool ListValue::Remove(size_t index, Value** out_value) {
834 if (index >= list_.size())
835 return false;
837 if (out_value)
838 *out_value = list_[index];
839 else
840 delete list_[index];
842 list_.erase(list_.begin() + index);
843 return true;
846 bool ListValue::Remove(const Value& value, size_t* index) {
847 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) {
848 if ((*i)->Equals(&value)) {
849 size_t previous_index = i - list_.begin();
850 delete *i;
851 list_.erase(i);
853 if (index)
854 *index = previous_index;
855 return true;
858 return false;
861 void ListValue::Append(Value* in_value) {
862 DCHECK(in_value);
863 list_.push_back(in_value);
866 bool ListValue::AppendIfNotPresent(Value* in_value) {
867 DCHECK(in_value);
868 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) {
869 if ((*i)->Equals(in_value)) {
870 delete in_value;
871 return false;
874 list_.push_back(in_value);
875 return true;
878 bool ListValue::Insert(size_t index, Value* in_value) {
879 DCHECK(in_value);
880 if (index > list_.size())
881 return false;
883 list_.insert(list_.begin() + index, in_value);
884 return true;
887 ListValue::const_iterator ListValue::Find(const Value& value) const {
888 return std::find_if(list_.begin(), list_.end(), ValueEquals(&value));
891 bool ListValue::GetAsList(ListValue** out_value) {
892 if (out_value)
893 *out_value = this;
894 return true;
897 bool ListValue::GetAsList(const ListValue** out_value) const {
898 if (out_value)
899 *out_value = this;
900 return true;
903 ListValue* ListValue::DeepCopy() const {
904 ListValue* result = new ListValue;
906 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
907 result->Append((*i)->DeepCopy());
909 return result;
912 bool ListValue::Equals(const Value* other) const {
913 if (other->GetType() != GetType())
914 return false;
916 const ListValue* other_list =
917 static_cast<const ListValue*>(other);
918 const_iterator lhs_it, rhs_it;
919 for (lhs_it = begin(), rhs_it = other_list->begin();
920 lhs_it != end() && rhs_it != other_list->end();
921 ++lhs_it, ++rhs_it) {
922 if (!(*lhs_it)->Equals(*rhs_it))
923 return false;
925 if (lhs_it != end() || rhs_it != other_list->end())
926 return false;
928 return true;
931 ValueSerializer::~ValueSerializer() {
934 } // namespace base