Revert 97987 - Switching NaCl IRT to be built inside the chrome build.
[chromium-blink-merge.git] / base / values.cc
blob799e100ea87b2f4015d9e5eb51dea14c2f04f327
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 "base/float_util.h"
8 #include "base/logging.h"
9 #include "base/string_util.h"
10 #include "base/utf_string_conversions.h"
12 namespace {
14 // Make a deep copy of |node|, but don't include empty lists or dictionaries
15 // in the copy. It's possible for this function to return NULL and it
16 // expects |node| to always be non-NULL.
17 Value* CopyWithoutEmptyChildren(Value* node) {
18 DCHECK(node);
19 switch (node->GetType()) {
20 case Value::TYPE_LIST: {
21 ListValue* list = static_cast<ListValue*>(node);
22 ListValue* copy = new ListValue;
23 for (ListValue::const_iterator it = list->begin(); it != list->end();
24 ++it) {
25 Value* child_copy = CopyWithoutEmptyChildren(*it);
26 if (child_copy)
27 copy->Append(child_copy);
29 if (!copy->empty())
30 return copy;
32 delete copy;
33 return NULL;
36 case Value::TYPE_DICTIONARY: {
37 DictionaryValue* dict = static_cast<DictionaryValue*>(node);
38 DictionaryValue* copy = new DictionaryValue;
39 for (DictionaryValue::key_iterator it = dict->begin_keys();
40 it != dict->end_keys(); ++it) {
41 Value* child = NULL;
42 bool rv = dict->GetWithoutPathExpansion(*it, &child);
43 DCHECK(rv);
44 Value* child_copy = CopyWithoutEmptyChildren(child);
45 if (child_copy)
46 copy->SetWithoutPathExpansion(*it, child_copy);
48 if (!copy->empty())
49 return copy;
51 delete copy;
52 return NULL;
55 default:
56 // For everything else, just make a copy.
57 return node->DeepCopy();
61 } // namespace
63 namespace base {
65 ///////////////////// Value ////////////////////
67 Value::~Value() {
68 #if !defined(OS_CHROMEOS)
69 CHECK(!check_on_delete_);
70 #endif
73 // static
74 Value* Value::CreateNullValue() {
75 return new Value(TYPE_NULL);
78 // static
79 FundamentalValue* Value::CreateBooleanValue(bool in_value) {
80 return new FundamentalValue(in_value);
83 // static
84 FundamentalValue* Value::CreateIntegerValue(int in_value) {
85 return new FundamentalValue(in_value);
88 // static
89 FundamentalValue* Value::CreateDoubleValue(double in_value) {
90 return new FundamentalValue(in_value);
93 // static
94 StringValue* Value::CreateStringValue(const std::string& in_value) {
95 return new StringValue(in_value);
98 // static
99 StringValue* Value::CreateStringValue(const string16& in_value) {
100 return new StringValue(in_value);
103 bool Value::GetAsBoolean(bool* out_value) const {
104 return false;
107 bool Value::GetAsInteger(int* out_value) const {
108 return false;
111 bool Value::GetAsDouble(double* out_value) const {
112 return false;
115 bool Value::GetAsString(std::string* out_value) const {
116 return false;
119 bool Value::GetAsString(string16* out_value) const {
120 return false;
123 bool Value::GetAsList(ListValue** out_value) {
124 return false;
127 bool Value::GetAsList(const ListValue** out_value) const {
128 return false;
131 Value* 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();
138 bool 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);
145 // static
146 bool Value::Equals(const Value* a, const Value* b) {
147 if ((a == NULL) && (b == NULL)) return true;
148 if ((a == NULL) ^ (b == NULL)) return false;
149 return a->Equals(b);
152 Value::Value(Type type)
153 : type_(type)
154 #if !defined(OS_CHROMEOS)
155 , check_on_delete_(false)
156 #endif
160 ///////////////////// FundamentalValue ////////////////////
162 FundamentalValue::FundamentalValue(bool in_value)
163 : Value(TYPE_BOOLEAN), boolean_value_(in_value) {
166 FundamentalValue::FundamentalValue(int in_value)
167 : Value(TYPE_INTEGER), integer_value_(in_value) {
170 FundamentalValue::FundamentalValue(double in_value)
171 : Value(TYPE_DOUBLE), double_value_(in_value) {
172 if (!IsFinite(double_value_)) {
173 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
174 << "values cannot be represented in JSON";
175 double_value_ = 0.0;
179 FundamentalValue::~FundamentalValue() {
182 bool FundamentalValue::GetAsBoolean(bool* out_value) const {
183 if (out_value && IsType(TYPE_BOOLEAN))
184 *out_value = boolean_value_;
185 return (IsType(TYPE_BOOLEAN));
188 bool FundamentalValue::GetAsInteger(int* out_value) const {
189 if (out_value && IsType(TYPE_INTEGER))
190 *out_value = integer_value_;
191 return (IsType(TYPE_INTEGER));
194 bool FundamentalValue::GetAsDouble(double* out_value) const {
195 if (out_value && IsType(TYPE_DOUBLE))
196 *out_value = double_value_;
197 else if (out_value && IsType(TYPE_INTEGER))
198 *out_value = integer_value_;
199 return (IsType(TYPE_DOUBLE) || IsType(TYPE_INTEGER));
202 FundamentalValue* FundamentalValue::DeepCopy() const {
203 switch (GetType()) {
204 case TYPE_BOOLEAN:
205 return CreateBooleanValue(boolean_value_);
207 case TYPE_INTEGER:
208 return CreateIntegerValue(integer_value_);
210 case TYPE_DOUBLE:
211 return CreateDoubleValue(double_value_);
213 default:
214 NOTREACHED();
215 return NULL;
219 bool FundamentalValue::Equals(const Value* other) const {
220 if (other->GetType() != GetType())
221 return false;
223 switch (GetType()) {
224 case TYPE_BOOLEAN: {
225 bool lhs, rhs;
226 return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs;
228 case TYPE_INTEGER: {
229 int lhs, rhs;
230 return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs;
232 case TYPE_DOUBLE: {
233 double lhs, rhs;
234 return GetAsDouble(&lhs) && other->GetAsDouble(&rhs) && lhs == rhs;
236 default:
237 NOTREACHED();
238 return false;
242 ///////////////////// StringValue ////////////////////
244 StringValue::StringValue(const std::string& in_value)
245 : Value(TYPE_STRING),
246 value_(in_value) {
247 DCHECK(IsStringUTF8(in_value));
250 StringValue::StringValue(const string16& in_value)
251 : Value(TYPE_STRING),
252 value_(UTF16ToUTF8(in_value)) {
255 StringValue::~StringValue() {
258 bool StringValue::GetAsString(std::string* out_value) const {
259 if (out_value)
260 *out_value = value_;
261 return true;
264 bool StringValue::GetAsString(string16* out_value) const {
265 if (out_value)
266 *out_value = UTF8ToUTF16(value_);
267 return true;
270 StringValue* StringValue::DeepCopy() const {
271 return CreateStringValue(value_);
274 bool StringValue::Equals(const Value* other) const {
275 if (other->GetType() != GetType())
276 return false;
277 std::string lhs, rhs;
278 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
281 ///////////////////// BinaryValue ////////////////////
283 BinaryValue::~BinaryValue() {
284 DCHECK(buffer_);
285 if (buffer_)
286 delete[] buffer_;
289 // static
290 BinaryValue* BinaryValue::Create(char* buffer, size_t size) {
291 if (!buffer)
292 return NULL;
294 return new BinaryValue(buffer, size);
297 // static
298 BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
299 size_t size) {
300 if (!buffer)
301 return NULL;
303 char* buffer_copy = new char[size];
304 memcpy(buffer_copy, buffer, size);
305 return new BinaryValue(buffer_copy, size);
308 BinaryValue* BinaryValue::DeepCopy() const {
309 return CreateWithCopiedBuffer(buffer_, size_);
312 bool BinaryValue::Equals(const Value* other) const {
313 if (other->GetType() != GetType())
314 return false;
315 const BinaryValue* other_binary = static_cast<const BinaryValue*>(other);
316 if (other_binary->size_ != size_)
317 return false;
318 return !memcmp(buffer_, other_binary->buffer_, size_);
321 BinaryValue::BinaryValue(char* buffer, size_t size)
322 : Value(TYPE_BINARY),
323 buffer_(buffer),
324 size_(size) {
325 DCHECK(buffer_);
328 ///////////////////// DictionaryValue ////////////////////
330 DictionaryValue::DictionaryValue()
331 : Value(TYPE_DICTIONARY) {
334 DictionaryValue::~DictionaryValue() {
335 Clear();
338 bool DictionaryValue::HasKey(const std::string& key) const {
339 DCHECK(IsStringUTF8(key));
340 ValueMap::const_iterator current_entry = dictionary_.find(key);
341 DCHECK((current_entry == dictionary_.end()) || current_entry->second);
342 return current_entry != dictionary_.end();
345 void DictionaryValue::Clear() {
346 ValueMap::iterator dict_iterator = dictionary_.begin();
347 while (dict_iterator != dictionary_.end()) {
348 delete dict_iterator->second;
349 ++dict_iterator;
352 dictionary_.clear();
355 void DictionaryValue::Set(const std::string& path, Value* in_value) {
356 DCHECK(IsStringUTF8(path));
357 DCHECK(in_value);
359 std::string current_path(path);
360 DictionaryValue* current_dictionary = this;
361 for (size_t delimiter_position = current_path.find('.');
362 delimiter_position != std::string::npos;
363 delimiter_position = current_path.find('.')) {
364 // Assume that we're indexing into a dictionary.
365 std::string key(current_path, 0, delimiter_position);
366 DictionaryValue* child_dictionary = NULL;
367 if (!current_dictionary->GetDictionary(key, &child_dictionary)) {
368 child_dictionary = new DictionaryValue;
369 current_dictionary->SetWithoutPathExpansion(key, child_dictionary);
372 current_dictionary = child_dictionary;
373 current_path.erase(0, delimiter_position + 1);
376 current_dictionary->SetWithoutPathExpansion(current_path, in_value);
379 void DictionaryValue::SetBoolean(const std::string& path, bool in_value) {
380 Set(path, CreateBooleanValue(in_value));
383 void DictionaryValue::SetInteger(const std::string& path, int in_value) {
384 Set(path, CreateIntegerValue(in_value));
387 void DictionaryValue::SetDouble(const std::string& path, double in_value) {
388 Set(path, CreateDoubleValue(in_value));
391 void DictionaryValue::SetString(const std::string& path,
392 const std::string& in_value) {
393 Set(path, CreateStringValue(in_value));
396 void DictionaryValue::SetString(const std::string& path,
397 const string16& in_value) {
398 Set(path, CreateStringValue(in_value));
401 void DictionaryValue::SetWithoutPathExpansion(const std::string& key,
402 Value* in_value) {
403 // If there's an existing value here, we need to delete it, because
404 // we own all our children.
405 if (HasKey(key)) {
406 DCHECK(dictionary_[key] != in_value); // This would be bogus
407 delete dictionary_[key];
410 dictionary_[key] = in_value;
413 bool DictionaryValue::Get(const std::string& path, Value** out_value) const {
414 DCHECK(IsStringUTF8(path));
415 std::string current_path(path);
416 const DictionaryValue* current_dictionary = this;
417 for (size_t delimiter_position = current_path.find('.');
418 delimiter_position != std::string::npos;
419 delimiter_position = current_path.find('.')) {
420 DictionaryValue* child_dictionary = NULL;
421 if (!current_dictionary->GetDictionary(
422 current_path.substr(0, delimiter_position), &child_dictionary))
423 return false;
425 current_dictionary = child_dictionary;
426 current_path.erase(0, delimiter_position + 1);
429 return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
432 bool DictionaryValue::GetBoolean(const std::string& path,
433 bool* bool_value) const {
434 Value* value;
435 if (!Get(path, &value))
436 return false;
438 return value->GetAsBoolean(bool_value);
441 bool DictionaryValue::GetInteger(const std::string& path,
442 int* out_value) const {
443 Value* value;
444 if (!Get(path, &value))
445 return false;
447 return value->GetAsInteger(out_value);
450 bool DictionaryValue::GetDouble(const std::string& path,
451 double* out_value) const {
452 Value* value;
453 if (!Get(path, &value))
454 return false;
456 return value->GetAsDouble(out_value);
459 bool DictionaryValue::GetString(const std::string& path,
460 std::string* out_value) const {
461 Value* value;
462 if (!Get(path, &value))
463 return false;
465 return value->GetAsString(out_value);
468 bool DictionaryValue::GetString(const std::string& path,
469 string16* out_value) const {
470 Value* value;
471 if (!Get(path, &value))
472 return false;
474 return value->GetAsString(out_value);
477 bool DictionaryValue::GetStringASCII(const std::string& path,
478 std::string* out_value) const {
479 std::string out;
480 if (!GetString(path, &out))
481 return false;
483 if (!IsStringASCII(out)) {
484 NOTREACHED();
485 return false;
488 out_value->assign(out);
489 return true;
492 bool DictionaryValue::GetBinary(const std::string& path,
493 BinaryValue** out_value) const {
494 Value* value;
495 bool result = Get(path, &value);
496 if (!result || !value->IsType(TYPE_BINARY))
497 return false;
499 if (out_value)
500 *out_value = static_cast<BinaryValue*>(value);
502 return true;
505 bool DictionaryValue::GetDictionary(const std::string& path,
506 DictionaryValue** out_value) const {
507 Value* value;
508 bool result = Get(path, &value);
509 if (!result || !value->IsType(TYPE_DICTIONARY))
510 return false;
512 if (out_value)
513 *out_value = static_cast<DictionaryValue*>(value);
515 return true;
518 bool DictionaryValue::GetList(const std::string& path,
519 ListValue** out_value) const {
520 Value* value;
521 bool result = Get(path, &value);
522 if (!result || !value->IsType(TYPE_LIST))
523 return false;
525 if (out_value)
526 *out_value = static_cast<ListValue*>(value);
528 return true;
531 bool DictionaryValue::GetWithoutPathExpansion(const std::string& key,
532 Value** out_value) const {
533 DCHECK(IsStringUTF8(key));
534 ValueMap::const_iterator entry_iterator = dictionary_.find(key);
535 if (entry_iterator == dictionary_.end())
536 return false;
538 Value* entry = entry_iterator->second;
539 if (out_value)
540 *out_value = entry;
541 return true;
544 bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::string& key,
545 int* out_value) const {
546 Value* value;
547 if (!GetWithoutPathExpansion(key, &value))
548 return false;
550 return value->GetAsInteger(out_value);
553 bool DictionaryValue::GetDoubleWithoutPathExpansion(const std::string& key,
554 double* out_value) const {
555 Value* value;
556 if (!GetWithoutPathExpansion(key, &value))
557 return false;
559 return value->GetAsDouble(out_value);
562 bool DictionaryValue::GetStringWithoutPathExpansion(
563 const std::string& key,
564 std::string* out_value) const {
565 Value* value;
566 if (!GetWithoutPathExpansion(key, &value))
567 return false;
569 return value->GetAsString(out_value);
572 bool DictionaryValue::GetStringWithoutPathExpansion(
573 const std::string& key,
574 string16* out_value) const {
575 Value* value;
576 if (!GetWithoutPathExpansion(key, &value))
577 return false;
579 return value->GetAsString(out_value);
582 bool DictionaryValue::GetDictionaryWithoutPathExpansion(
583 const std::string& key,
584 DictionaryValue** out_value) const {
585 Value* value;
586 bool result = GetWithoutPathExpansion(key, &value);
587 if (!result || !value->IsType(TYPE_DICTIONARY))
588 return false;
590 if (out_value)
591 *out_value = static_cast<DictionaryValue*>(value);
593 return true;
596 bool DictionaryValue::GetListWithoutPathExpansion(const std::string& key,
597 ListValue** out_value) const {
598 Value* value;
599 bool result = GetWithoutPathExpansion(key, &value);
600 if (!result || !value->IsType(TYPE_LIST))
601 return false;
603 if (out_value)
604 *out_value = static_cast<ListValue*>(value);
606 return true;
609 bool DictionaryValue::Remove(const std::string& path, Value** out_value) {
610 DCHECK(IsStringUTF8(path));
611 std::string current_path(path);
612 DictionaryValue* current_dictionary = this;
613 size_t delimiter_position = current_path.rfind('.');
614 if (delimiter_position != std::string::npos) {
615 if (!GetDictionary(current_path.substr(0, delimiter_position),
616 &current_dictionary))
617 return false;
618 current_path.erase(0, delimiter_position + 1);
621 return current_dictionary->RemoveWithoutPathExpansion(current_path,
622 out_value);
625 bool DictionaryValue::RemoveWithoutPathExpansion(const std::string& key,
626 Value** out_value) {
627 DCHECK(IsStringUTF8(key));
628 ValueMap::iterator entry_iterator = dictionary_.find(key);
629 if (entry_iterator == dictionary_.end())
630 return false;
632 Value* entry = entry_iterator->second;
633 if (out_value)
634 *out_value = entry;
635 else
636 delete entry;
637 dictionary_.erase(entry_iterator);
638 return true;
641 DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() {
642 Value* copy = CopyWithoutEmptyChildren(this);
643 return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue;
646 void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
647 for (DictionaryValue::key_iterator key(dictionary->begin_keys());
648 key != dictionary->end_keys(); ++key) {
649 Value* merge_value;
650 if (dictionary->GetWithoutPathExpansion(*key, &merge_value)) {
651 // Check whether we have to merge dictionaries.
652 if (merge_value->IsType(Value::TYPE_DICTIONARY)) {
653 DictionaryValue* sub_dict;
654 if (GetDictionaryWithoutPathExpansion(*key, &sub_dict)) {
655 sub_dict->MergeDictionary(
656 static_cast<const DictionaryValue*>(merge_value));
657 continue;
660 // All other cases: Make a copy and hook it up.
661 SetWithoutPathExpansion(*key, merge_value->DeepCopy());
666 DictionaryValue* DictionaryValue::DeepCopy() const {
667 DictionaryValue* result = new DictionaryValue;
669 for (ValueMap::const_iterator current_entry(dictionary_.begin());
670 current_entry != dictionary_.end(); ++current_entry) {
671 result->SetWithoutPathExpansion(current_entry->first,
672 current_entry->second->DeepCopy());
675 return result;
678 bool DictionaryValue::Equals(const Value* other) const {
679 if (other->GetType() != GetType())
680 return false;
682 const DictionaryValue* other_dict =
683 static_cast<const DictionaryValue*>(other);
684 key_iterator lhs_it(begin_keys());
685 key_iterator rhs_it(other_dict->begin_keys());
686 while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) {
687 Value* lhs;
688 Value* rhs;
689 if (*lhs_it != *rhs_it ||
690 !GetWithoutPathExpansion(*lhs_it, &lhs) ||
691 !other_dict->GetWithoutPathExpansion(*rhs_it, &rhs) ||
692 !lhs->Equals(rhs)) {
693 return false;
695 ++lhs_it;
696 ++rhs_it;
698 if (lhs_it != end_keys() || rhs_it != other_dict->end_keys())
699 return false;
701 return true;
704 ///////////////////// ListValue ////////////////////
706 ListValue::ListValue() : Value(TYPE_LIST) {
709 ListValue::~ListValue() {
710 Clear();
713 void ListValue::Clear() {
714 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
715 delete *i;
716 list_.clear();
719 bool ListValue::Set(size_t index, Value* in_value) {
720 if (!in_value)
721 return false;
723 if (index >= list_.size()) {
724 // Pad out any intermediate indexes with null settings
725 while (index > list_.size())
726 Append(CreateNullValue());
727 Append(in_value);
728 } else {
729 DCHECK(list_[index] != in_value);
730 delete list_[index];
731 list_[index] = in_value;
733 return true;
736 bool ListValue::Get(size_t index, Value** out_value) const {
737 if (index >= list_.size())
738 return false;
740 if (out_value)
741 *out_value = list_[index];
743 return true;
746 bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
747 Value* value;
748 if (!Get(index, &value))
749 return false;
751 return value->GetAsBoolean(bool_value);
754 bool ListValue::GetInteger(size_t index, int* out_value) const {
755 Value* value;
756 if (!Get(index, &value))
757 return false;
759 return value->GetAsInteger(out_value);
762 bool ListValue::GetDouble(size_t index, double* out_value) const {
763 Value* value;
764 if (!Get(index, &value))
765 return false;
767 return value->GetAsDouble(out_value);
770 bool ListValue::GetString(size_t index, std::string* out_value) const {
771 Value* value;
772 if (!Get(index, &value))
773 return false;
775 return value->GetAsString(out_value);
778 bool ListValue::GetString(size_t index, string16* out_value) const {
779 Value* value;
780 if (!Get(index, &value))
781 return false;
783 return value->GetAsString(out_value);
786 bool ListValue::GetBinary(size_t index, BinaryValue** out_value) const {
787 Value* value;
788 bool result = Get(index, &value);
789 if (!result || !value->IsType(TYPE_BINARY))
790 return false;
792 if (out_value)
793 *out_value = static_cast<BinaryValue*>(value);
795 return true;
798 bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) const {
799 Value* value;
800 bool result = Get(index, &value);
801 if (!result || !value->IsType(TYPE_DICTIONARY))
802 return false;
804 if (out_value)
805 *out_value = static_cast<DictionaryValue*>(value);
807 return true;
810 bool ListValue::GetList(size_t index, ListValue** out_value) const {
811 Value* value;
812 bool result = Get(index, &value);
813 if (!result || !value->IsType(TYPE_LIST))
814 return false;
816 if (out_value)
817 *out_value = static_cast<ListValue*>(value);
819 return true;
822 bool ListValue::Remove(size_t index, Value** out_value) {
823 if (index >= list_.size())
824 return false;
826 if (out_value)
827 *out_value = list_[index];
828 else
829 delete list_[index];
831 list_.erase(list_.begin() + index);
832 return true;
835 bool ListValue::Remove(const Value& value, size_t* index) {
836 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) {
837 if ((*i)->Equals(&value)) {
838 size_t previous_index = i - list_.begin();
839 delete *i;
840 list_.erase(i);
842 if (index)
843 *index = previous_index;
844 return true;
847 return false;
850 void ListValue::Append(Value* in_value) {
851 DCHECK(in_value);
852 list_.push_back(in_value);
855 bool ListValue::AppendIfNotPresent(Value* in_value) {
856 DCHECK(in_value);
857 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) {
858 if ((*i)->Equals(in_value)) {
859 delete in_value;
860 return false;
863 list_.push_back(in_value);
864 return true;
867 bool ListValue::Insert(size_t index, Value* in_value) {
868 DCHECK(in_value);
869 if (index > list_.size())
870 return false;
872 list_.insert(list_.begin() + index, in_value);
873 return true;
876 bool ListValue::GetAsList(ListValue** out_value) {
877 if (out_value)
878 *out_value = this;
879 return true;
882 bool ListValue::GetAsList(const ListValue** out_value) const {
883 if (out_value)
884 *out_value = this;
885 return true;
888 ListValue* ListValue::DeepCopy() const {
889 ListValue* result = new ListValue;
891 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
892 result->Append((*i)->DeepCopy());
894 return result;
897 bool ListValue::Equals(const Value* other) const {
898 if (other->GetType() != GetType())
899 return false;
901 const ListValue* other_list =
902 static_cast<const ListValue*>(other);
903 const_iterator lhs_it, rhs_it;
904 for (lhs_it = begin(), rhs_it = other_list->begin();
905 lhs_it != end() && rhs_it != other_list->end();
906 ++lhs_it, ++rhs_it) {
907 if (!(*lhs_it)->Equals(*rhs_it))
908 return false;
910 if (lhs_it != end() || rhs_it != other_list->end())
911 return false;
913 return true;
916 ValueSerializer::~ValueSerializer() {
919 } // namespace base