Fixed last bookmark button hiding behavior.
[chromium-blink-merge.git] / base / values.cc
blob4768774b03db9f1bcd3cf49056b071325b32f494
1 // Copyright (c) 2012 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>
8 #include <ostream>
10 #include "base/float_util.h"
11 #include "base/json/json_writer.h"
12 #include "base/logging.h"
13 #include "base/string_util.h"
14 #include "base/utf_string_conversions.h"
16 namespace {
18 // Make a deep copy of |node|, but don't include empty lists or dictionaries
19 // in the copy. It's possible for this function to return NULL and it
20 // expects |node| to always be non-NULL.
21 Value* CopyWithoutEmptyChildren(const Value* node) {
22 DCHECK(node);
23 switch (node->GetType()) {
24 case Value::TYPE_LIST: {
25 const ListValue* list = static_cast<const ListValue*>(node);
26 ListValue* copy = new ListValue;
27 for (ListValue::const_iterator it = list->begin(); it != list->end();
28 ++it) {
29 Value* child_copy = CopyWithoutEmptyChildren(*it);
30 if (child_copy)
31 copy->Append(child_copy);
33 if (!copy->empty())
34 return copy;
36 delete copy;
37 return NULL;
40 case Value::TYPE_DICTIONARY: {
41 const DictionaryValue* dict = static_cast<const DictionaryValue*>(node);
42 DictionaryValue* copy = new DictionaryValue;
43 for (DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
44 Value* child_copy = CopyWithoutEmptyChildren(&it.value());
45 if (child_copy)
46 copy->SetWithoutPathExpansion(it.key(), 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 // A small functor for comparing Values for std::find_if and similar.
62 class ValueEquals {
63 public:
64 // Pass the value against which all consecutive calls of the () operator will
65 // compare their argument to. This Value object must not be destroyed while
66 // the ValueEquals is in use.
67 explicit ValueEquals(const Value* first) : first_(first) { }
69 bool operator ()(const Value* second) const {
70 return first_->Equals(second);
73 private:
74 const Value* first_;
77 } // namespace
79 namespace base {
81 ///////////////////// Value ////////////////////
83 Value::~Value() {
86 // static
87 Value* Value::CreateNullValue() {
88 return new Value(TYPE_NULL);
91 // static
92 FundamentalValue* Value::CreateBooleanValue(bool in_value) {
93 return new FundamentalValue(in_value);
96 // static
97 FundamentalValue* Value::CreateIntegerValue(int in_value) {
98 return new FundamentalValue(in_value);
101 // static
102 FundamentalValue* Value::CreateDoubleValue(double in_value) {
103 return new FundamentalValue(in_value);
106 // static
107 StringValue* Value::CreateStringValue(const std::string& in_value) {
108 return new StringValue(in_value);
111 // static
112 StringValue* Value::CreateStringValue(const string16& in_value) {
113 return new StringValue(in_value);
116 bool Value::GetAsBoolean(bool* out_value) const {
117 return false;
120 bool Value::GetAsInteger(int* out_value) const {
121 return false;
124 bool Value::GetAsDouble(double* out_value) const {
125 return false;
128 bool Value::GetAsString(std::string* out_value) const {
129 return false;
132 bool Value::GetAsString(string16* out_value) const {
133 return false;
136 bool Value::GetAsList(ListValue** out_value) {
137 return false;
140 bool Value::GetAsList(const ListValue** out_value) const {
141 return false;
144 bool Value::GetAsDictionary(DictionaryValue** out_value) {
145 return false;
148 bool Value::GetAsDictionary(const DictionaryValue** out_value) const {
149 return false;
152 Value* Value::DeepCopy() 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 CreateNullValue();
159 bool Value::Equals(const Value* other) const {
160 // This method should only be getting called for null Values--all subclasses
161 // need to provide their own implementation;.
162 DCHECK(IsType(TYPE_NULL));
163 return other->IsType(TYPE_NULL);
166 // static
167 bool Value::Equals(const Value* a, const Value* b) {
168 if ((a == NULL) && (b == NULL)) return true;
169 if ((a == NULL) ^ (b == NULL)) return false;
170 return a->Equals(b);
173 Value::Value(Type type) : type_(type) {}
175 Value::Value(const Value& that) : type_(that.type_) {}
177 Value& Value::operator=(const Value& that) {
178 type_ = that.type_;
179 return *this;
182 ///////////////////// FundamentalValue ////////////////////
184 FundamentalValue::FundamentalValue(bool in_value)
185 : Value(TYPE_BOOLEAN), boolean_value_(in_value) {
188 FundamentalValue::FundamentalValue(int in_value)
189 : Value(TYPE_INTEGER), integer_value_(in_value) {
192 FundamentalValue::FundamentalValue(double in_value)
193 : Value(TYPE_DOUBLE), double_value_(in_value) {
194 if (!IsFinite(double_value_)) {
195 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
196 << "values cannot be represented in JSON";
197 double_value_ = 0.0;
201 FundamentalValue::~FundamentalValue() {
204 bool FundamentalValue::GetAsBoolean(bool* out_value) const {
205 if (out_value && IsType(TYPE_BOOLEAN))
206 *out_value = boolean_value_;
207 return (IsType(TYPE_BOOLEAN));
210 bool FundamentalValue::GetAsInteger(int* out_value) const {
211 if (out_value && IsType(TYPE_INTEGER))
212 *out_value = integer_value_;
213 return (IsType(TYPE_INTEGER));
216 bool FundamentalValue::GetAsDouble(double* out_value) const {
217 if (out_value && IsType(TYPE_DOUBLE))
218 *out_value = double_value_;
219 else if (out_value && IsType(TYPE_INTEGER))
220 *out_value = integer_value_;
221 return (IsType(TYPE_DOUBLE) || IsType(TYPE_INTEGER));
224 FundamentalValue* FundamentalValue::DeepCopy() const {
225 switch (GetType()) {
226 case TYPE_BOOLEAN:
227 return CreateBooleanValue(boolean_value_);
229 case TYPE_INTEGER:
230 return CreateIntegerValue(integer_value_);
232 case TYPE_DOUBLE:
233 return CreateDoubleValue(double_value_);
235 default:
236 NOTREACHED();
237 return NULL;
241 bool FundamentalValue::Equals(const Value* other) const {
242 if (other->GetType() != GetType())
243 return false;
245 switch (GetType()) {
246 case TYPE_BOOLEAN: {
247 bool lhs, rhs;
248 return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs;
250 case TYPE_INTEGER: {
251 int lhs, rhs;
252 return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs;
254 case TYPE_DOUBLE: {
255 double lhs, rhs;
256 return GetAsDouble(&lhs) && other->GetAsDouble(&rhs) && lhs == rhs;
258 default:
259 NOTREACHED();
260 return false;
264 ///////////////////// StringValue ////////////////////
266 StringValue::StringValue(const std::string& in_value)
267 : Value(TYPE_STRING),
268 value_(in_value) {
269 DCHECK(IsStringUTF8(in_value));
272 StringValue::StringValue(const string16& in_value)
273 : Value(TYPE_STRING),
274 value_(UTF16ToUTF8(in_value)) {
277 StringValue::~StringValue() {
280 bool StringValue::GetAsString(std::string* out_value) const {
281 if (out_value)
282 *out_value = value_;
283 return true;
286 bool StringValue::GetAsString(string16* out_value) const {
287 if (out_value)
288 *out_value = UTF8ToUTF16(value_);
289 return true;
292 StringValue* StringValue::DeepCopy() const {
293 return CreateStringValue(value_);
296 bool StringValue::Equals(const Value* other) const {
297 if (other->GetType() != GetType())
298 return false;
299 std::string lhs, rhs;
300 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
303 ///////////////////// BinaryValue ////////////////////
305 BinaryValue::BinaryValue()
306 : Value(TYPE_BINARY),
307 size_(0) {
310 BinaryValue::BinaryValue(scoped_ptr<char[]> buffer, size_t size)
311 : Value(TYPE_BINARY),
312 buffer_(buffer.Pass()),
313 size_(size) {
316 BinaryValue::~BinaryValue() {
319 // static
320 BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
321 size_t size) {
322 char* buffer_copy = new char[size];
323 memcpy(buffer_copy, buffer, size);
324 scoped_ptr<char[]> scoped_buffer_copy(buffer_copy);
325 return new BinaryValue(scoped_buffer_copy.Pass(), size);
328 BinaryValue* BinaryValue::DeepCopy() const {
329 return CreateWithCopiedBuffer(buffer_.get(), size_);
332 bool BinaryValue::Equals(const Value* other) const {
333 if (other->GetType() != GetType())
334 return false;
335 const BinaryValue* other_binary = static_cast<const BinaryValue*>(other);
336 if (other_binary->size_ != size_)
337 return false;
338 return !memcmp(GetBuffer(), other_binary->GetBuffer(), size_);
341 ///////////////////// DictionaryValue ////////////////////
343 DictionaryValue::DictionaryValue()
344 : Value(TYPE_DICTIONARY) {
347 DictionaryValue::~DictionaryValue() {
348 Clear();
351 bool DictionaryValue::GetAsDictionary(DictionaryValue** out_value) {
352 if (out_value)
353 *out_value = this;
354 return true;
357 bool DictionaryValue::GetAsDictionary(const DictionaryValue** out_value) const {
358 if (out_value)
359 *out_value = this;
360 return true;
363 bool DictionaryValue::HasKey(const std::string& key) const {
364 DCHECK(IsStringUTF8(key));
365 ValueMap::const_iterator current_entry = dictionary_.find(key);
366 DCHECK((current_entry == dictionary_.end()) || current_entry->second);
367 return current_entry != dictionary_.end();
370 void DictionaryValue::Clear() {
371 ValueMap::iterator dict_iterator = dictionary_.begin();
372 while (dict_iterator != dictionary_.end()) {
373 delete dict_iterator->second;
374 ++dict_iterator;
377 dictionary_.clear();
380 void DictionaryValue::Set(const std::string& path, Value* in_value) {
381 DCHECK(IsStringUTF8(path));
382 DCHECK(in_value);
384 std::string current_path(path);
385 DictionaryValue* current_dictionary = this;
386 for (size_t delimiter_position = current_path.find('.');
387 delimiter_position != std::string::npos;
388 delimiter_position = current_path.find('.')) {
389 // Assume that we're indexing into a dictionary.
390 std::string key(current_path, 0, delimiter_position);
391 DictionaryValue* child_dictionary = NULL;
392 if (!current_dictionary->GetDictionary(key, &child_dictionary)) {
393 child_dictionary = new DictionaryValue;
394 current_dictionary->SetWithoutPathExpansion(key, child_dictionary);
397 current_dictionary = child_dictionary;
398 current_path.erase(0, delimiter_position + 1);
401 current_dictionary->SetWithoutPathExpansion(current_path, in_value);
404 void DictionaryValue::SetBoolean(const std::string& path, bool in_value) {
405 Set(path, CreateBooleanValue(in_value));
408 void DictionaryValue::SetInteger(const std::string& path, int in_value) {
409 Set(path, CreateIntegerValue(in_value));
412 void DictionaryValue::SetDouble(const std::string& path, double in_value) {
413 Set(path, CreateDoubleValue(in_value));
416 void DictionaryValue::SetString(const std::string& path,
417 const std::string& in_value) {
418 Set(path, CreateStringValue(in_value));
421 void DictionaryValue::SetString(const std::string& path,
422 const string16& in_value) {
423 Set(path, CreateStringValue(in_value));
426 void DictionaryValue::SetWithoutPathExpansion(const std::string& key,
427 Value* in_value) {
428 // If there's an existing value here, we need to delete it, because
429 // we own all our children.
430 std::pair<ValueMap::iterator, bool> ins_res =
431 dictionary_.insert(std::make_pair(key, in_value));
432 if (!ins_res.second) {
433 DCHECK_NE(ins_res.first->second, in_value); // This would be bogus
434 delete ins_res.first->second;
435 ins_res.first->second = in_value;
439 void DictionaryValue::SetBooleanWithoutPathExpansion(
440 const std::string& path, bool in_value) {
441 SetWithoutPathExpansion(path, CreateBooleanValue(in_value));
444 void DictionaryValue::SetIntegerWithoutPathExpansion(
445 const std::string& path, int in_value) {
446 SetWithoutPathExpansion(path, CreateIntegerValue(in_value));
449 void DictionaryValue::SetDoubleWithoutPathExpansion(
450 const std::string& path, double in_value) {
451 SetWithoutPathExpansion(path, CreateDoubleValue(in_value));
454 void DictionaryValue::SetStringWithoutPathExpansion(
455 const std::string& path, const std::string& in_value) {
456 SetWithoutPathExpansion(path, CreateStringValue(in_value));
459 void DictionaryValue::SetStringWithoutPathExpansion(
460 const std::string& path, const string16& in_value) {
461 SetWithoutPathExpansion(path, CreateStringValue(in_value));
464 bool DictionaryValue::Get(
465 const std::string& path, const Value** out_value) const {
466 DCHECK(IsStringUTF8(path));
467 std::string current_path(path);
468 const DictionaryValue* current_dictionary = this;
469 for (size_t delimiter_position = current_path.find('.');
470 delimiter_position != std::string::npos;
471 delimiter_position = current_path.find('.')) {
472 const DictionaryValue* child_dictionary = NULL;
473 if (!current_dictionary->GetDictionary(
474 current_path.substr(0, delimiter_position), &child_dictionary))
475 return false;
477 current_dictionary = child_dictionary;
478 current_path.erase(0, delimiter_position + 1);
481 return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
484 bool DictionaryValue::Get(const std::string& path, Value** out_value) {
485 return static_cast<const DictionaryValue&>(*this).Get(
486 path,
487 const_cast<const Value**>(out_value));
490 bool DictionaryValue::GetBoolean(const std::string& path,
491 bool* bool_value) const {
492 const Value* value;
493 if (!Get(path, &value))
494 return false;
496 return value->GetAsBoolean(bool_value);
499 bool DictionaryValue::GetInteger(const std::string& path,
500 int* out_value) const {
501 const Value* value;
502 if (!Get(path, &value))
503 return false;
505 return value->GetAsInteger(out_value);
508 bool DictionaryValue::GetDouble(const std::string& path,
509 double* out_value) const {
510 const Value* value;
511 if (!Get(path, &value))
512 return false;
514 return value->GetAsDouble(out_value);
517 bool DictionaryValue::GetString(const std::string& path,
518 std::string* out_value) const {
519 const Value* value;
520 if (!Get(path, &value))
521 return false;
523 return value->GetAsString(out_value);
526 bool DictionaryValue::GetString(const std::string& path,
527 string16* out_value) const {
528 const Value* value;
529 if (!Get(path, &value))
530 return false;
532 return value->GetAsString(out_value);
535 bool DictionaryValue::GetStringASCII(const std::string& path,
536 std::string* out_value) const {
537 std::string out;
538 if (!GetString(path, &out))
539 return false;
541 if (!IsStringASCII(out)) {
542 NOTREACHED();
543 return false;
546 out_value->assign(out);
547 return true;
550 bool DictionaryValue::GetBinary(const std::string& path,
551 const BinaryValue** out_value) const {
552 const Value* value;
553 bool result = Get(path, &value);
554 if (!result || !value->IsType(TYPE_BINARY))
555 return false;
557 if (out_value)
558 *out_value = static_cast<const BinaryValue*>(value);
560 return true;
563 bool DictionaryValue::GetBinary(const std::string& path,
564 BinaryValue** out_value) {
565 return static_cast<const DictionaryValue&>(*this).GetBinary(
566 path,
567 const_cast<const BinaryValue**>(out_value));
570 bool DictionaryValue::GetDictionary(const std::string& path,
571 const DictionaryValue** out_value) const {
572 const Value* value;
573 bool result = Get(path, &value);
574 if (!result || !value->IsType(TYPE_DICTIONARY))
575 return false;
577 if (out_value)
578 *out_value = static_cast<const DictionaryValue*>(value);
580 return true;
583 bool DictionaryValue::GetDictionary(const std::string& path,
584 DictionaryValue** out_value) {
585 return static_cast<const DictionaryValue&>(*this).GetDictionary(
586 path,
587 const_cast<const DictionaryValue**>(out_value));
590 bool DictionaryValue::GetList(const std::string& path,
591 const ListValue** out_value) const {
592 const Value* value;
593 bool result = Get(path, &value);
594 if (!result || !value->IsType(TYPE_LIST))
595 return false;
597 if (out_value)
598 *out_value = static_cast<const ListValue*>(value);
600 return true;
603 bool DictionaryValue::GetList(const std::string& path, ListValue** out_value) {
604 return static_cast<const DictionaryValue&>(*this).GetList(
605 path,
606 const_cast<const ListValue**>(out_value));
609 bool DictionaryValue::GetWithoutPathExpansion(const std::string& key,
610 const Value** out_value) const {
611 DCHECK(IsStringUTF8(key));
612 ValueMap::const_iterator entry_iterator = dictionary_.find(key);
613 if (entry_iterator == dictionary_.end())
614 return false;
616 const Value* entry = entry_iterator->second;
617 if (out_value)
618 *out_value = entry;
619 return true;
622 bool DictionaryValue::GetWithoutPathExpansion(const std::string& key,
623 Value** out_value) {
624 return static_cast<const DictionaryValue&>(*this).GetWithoutPathExpansion(
625 key,
626 const_cast<const Value**>(out_value));
629 bool DictionaryValue::GetBooleanWithoutPathExpansion(const std::string& key,
630 bool* out_value) const {
631 const Value* value;
632 if (!GetWithoutPathExpansion(key, &value))
633 return false;
635 return value->GetAsBoolean(out_value);
638 bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::string& key,
639 int* out_value) const {
640 const Value* value;
641 if (!GetWithoutPathExpansion(key, &value))
642 return false;
644 return value->GetAsInteger(out_value);
647 bool DictionaryValue::GetDoubleWithoutPathExpansion(const std::string& key,
648 double* out_value) const {
649 const Value* value;
650 if (!GetWithoutPathExpansion(key, &value))
651 return false;
653 return value->GetAsDouble(out_value);
656 bool DictionaryValue::GetStringWithoutPathExpansion(
657 const std::string& key,
658 std::string* out_value) const {
659 const Value* value;
660 if (!GetWithoutPathExpansion(key, &value))
661 return false;
663 return value->GetAsString(out_value);
666 bool DictionaryValue::GetStringWithoutPathExpansion(const std::string& key,
667 string16* out_value) const {
668 const Value* value;
669 if (!GetWithoutPathExpansion(key, &value))
670 return false;
672 return value->GetAsString(out_value);
675 bool DictionaryValue::GetDictionaryWithoutPathExpansion(
676 const std::string& key,
677 const DictionaryValue** out_value) const {
678 const Value* value;
679 bool result = GetWithoutPathExpansion(key, &value);
680 if (!result || !value->IsType(TYPE_DICTIONARY))
681 return false;
683 if (out_value)
684 *out_value = static_cast<const DictionaryValue*>(value);
686 return true;
689 bool DictionaryValue::GetDictionaryWithoutPathExpansion(
690 const std::string& key,
691 DictionaryValue** out_value) {
692 const DictionaryValue& const_this =
693 static_cast<const DictionaryValue&>(*this);
694 return const_this.GetDictionaryWithoutPathExpansion(
695 key,
696 const_cast<const DictionaryValue**>(out_value));
699 bool DictionaryValue::GetListWithoutPathExpansion(
700 const std::string& key,
701 const ListValue** out_value) const {
702 const Value* value;
703 bool result = GetWithoutPathExpansion(key, &value);
704 if (!result || !value->IsType(TYPE_LIST))
705 return false;
707 if (out_value)
708 *out_value = static_cast<const ListValue*>(value);
710 return true;
713 bool DictionaryValue::GetListWithoutPathExpansion(const std::string& key,
714 ListValue** out_value) {
715 return
716 static_cast<const DictionaryValue&>(*this).GetListWithoutPathExpansion(
717 key,
718 const_cast<const ListValue**>(out_value));
721 bool DictionaryValue::Remove(const std::string& path, Value** out_value) {
722 DCHECK(IsStringUTF8(path));
723 std::string current_path(path);
724 DictionaryValue* current_dictionary = this;
725 size_t delimiter_position = current_path.rfind('.');
726 if (delimiter_position != std::string::npos) {
727 if (!GetDictionary(current_path.substr(0, delimiter_position),
728 &current_dictionary))
729 return false;
730 current_path.erase(0, delimiter_position + 1);
733 return current_dictionary->RemoveWithoutPathExpansion(current_path,
734 out_value);
737 bool DictionaryValue::RemoveWithoutPathExpansion(const std::string& key,
738 Value** out_value) {
739 DCHECK(IsStringUTF8(key));
740 ValueMap::iterator entry_iterator = dictionary_.find(key);
741 if (entry_iterator == dictionary_.end())
742 return false;
744 Value* entry = entry_iterator->second;
745 if (out_value)
746 *out_value = entry;
747 else
748 delete entry;
749 dictionary_.erase(entry_iterator);
750 return true;
753 DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() {
754 Value* copy = CopyWithoutEmptyChildren(this);
755 return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue;
758 void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
759 for (DictionaryValue::key_iterator key(dictionary->begin_keys());
760 key != dictionary->end_keys(); ++key) {
761 const Value* merge_value;
762 if (dictionary->GetWithoutPathExpansion(*key, &merge_value)) {
763 // Check whether we have to merge dictionaries.
764 if (merge_value->IsType(Value::TYPE_DICTIONARY)) {
765 DictionaryValue* sub_dict;
766 if (GetDictionaryWithoutPathExpansion(*key, &sub_dict)) {
767 sub_dict->MergeDictionary(
768 static_cast<const DictionaryValue*>(merge_value));
769 continue;
772 // All other cases: Make a copy and hook it up.
773 SetWithoutPathExpansion(*key, merge_value->DeepCopy());
778 void DictionaryValue::Swap(DictionaryValue* other) {
779 dictionary_.swap(other->dictionary_);
782 DictionaryValue::key_iterator::key_iterator(ValueMap::const_iterator itr) {
783 itr_ = itr;
786 DictionaryValue::key_iterator::key_iterator(const key_iterator& rhs) {
787 itr_ = rhs.itr_;
790 DictionaryValue::Iterator::Iterator(const DictionaryValue& target)
791 : target_(target),
792 it_(target.dictionary_.begin()) {}
794 DictionaryValue* DictionaryValue::DeepCopy() const {
795 DictionaryValue* result = new DictionaryValue;
797 for (ValueMap::const_iterator current_entry(dictionary_.begin());
798 current_entry != dictionary_.end(); ++current_entry) {
799 result->SetWithoutPathExpansion(current_entry->first,
800 current_entry->second->DeepCopy());
803 return result;
806 bool DictionaryValue::Equals(const Value* other) const {
807 if (other->GetType() != GetType())
808 return false;
810 const DictionaryValue* other_dict =
811 static_cast<const DictionaryValue*>(other);
812 key_iterator lhs_it(begin_keys());
813 key_iterator rhs_it(other_dict->begin_keys());
814 while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) {
815 const Value* lhs;
816 const Value* rhs;
817 if (*lhs_it != *rhs_it ||
818 !GetWithoutPathExpansion(*lhs_it, &lhs) ||
819 !other_dict->GetWithoutPathExpansion(*rhs_it, &rhs) ||
820 !lhs->Equals(rhs)) {
821 return false;
823 ++lhs_it;
824 ++rhs_it;
826 if (lhs_it != end_keys() || rhs_it != other_dict->end_keys())
827 return false;
829 return true;
832 ///////////////////// ListValue ////////////////////
834 ListValue::ListValue() : Value(TYPE_LIST) {
837 ListValue::~ListValue() {
838 Clear();
841 void ListValue::Clear() {
842 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
843 delete *i;
844 list_.clear();
847 bool ListValue::Set(size_t index, Value* in_value) {
848 if (!in_value)
849 return false;
851 if (index >= list_.size()) {
852 // Pad out any intermediate indexes with null settings
853 while (index > list_.size())
854 Append(CreateNullValue());
855 Append(in_value);
856 } else {
857 DCHECK(list_[index] != in_value);
858 delete list_[index];
859 list_[index] = in_value;
861 return true;
864 bool ListValue::Get(size_t index, const Value** out_value) const {
865 if (index >= list_.size())
866 return false;
868 if (out_value)
869 *out_value = list_[index];
871 return true;
874 bool ListValue::Get(size_t index, Value** out_value) {
875 return static_cast<const ListValue&>(*this).Get(
876 index,
877 const_cast<const Value**>(out_value));
880 bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
881 const Value* value;
882 if (!Get(index, &value))
883 return false;
885 return value->GetAsBoolean(bool_value);
888 bool ListValue::GetInteger(size_t index, int* out_value) const {
889 const Value* value;
890 if (!Get(index, &value))
891 return false;
893 return value->GetAsInteger(out_value);
896 bool ListValue::GetDouble(size_t index, double* out_value) const {
897 const Value* value;
898 if (!Get(index, &value))
899 return false;
901 return value->GetAsDouble(out_value);
904 bool ListValue::GetString(size_t index, std::string* out_value) const {
905 const Value* value;
906 if (!Get(index, &value))
907 return false;
909 return value->GetAsString(out_value);
912 bool ListValue::GetString(size_t index, string16* out_value) const {
913 const Value* value;
914 if (!Get(index, &value))
915 return false;
917 return value->GetAsString(out_value);
920 bool ListValue::GetBinary(size_t index, const BinaryValue** out_value) const {
921 const Value* value;
922 bool result = Get(index, &value);
923 if (!result || !value->IsType(TYPE_BINARY))
924 return false;
926 if (out_value)
927 *out_value = static_cast<const BinaryValue*>(value);
929 return true;
932 bool ListValue::GetBinary(size_t index, BinaryValue** out_value) {
933 return static_cast<const ListValue&>(*this).GetBinary(
934 index,
935 const_cast<const BinaryValue**>(out_value));
938 bool ListValue::GetDictionary(size_t index,
939 const DictionaryValue** out_value) const {
940 const Value* value;
941 bool result = Get(index, &value);
942 if (!result || !value->IsType(TYPE_DICTIONARY))
943 return false;
945 if (out_value)
946 *out_value = static_cast<const DictionaryValue*>(value);
948 return true;
951 bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) {
952 return static_cast<const ListValue&>(*this).GetDictionary(
953 index,
954 const_cast<const DictionaryValue**>(out_value));
957 bool ListValue::GetList(size_t index, const ListValue** out_value) const {
958 const Value* value;
959 bool result = Get(index, &value);
960 if (!result || !value->IsType(TYPE_LIST))
961 return false;
963 if (out_value)
964 *out_value = static_cast<const ListValue*>(value);
966 return true;
969 bool ListValue::GetList(size_t index, ListValue** out_value) {
970 return static_cast<const ListValue&>(*this).GetList(
971 index,
972 const_cast<const ListValue**>(out_value));
975 bool ListValue::Remove(size_t index, Value** out_value) {
976 if (index >= list_.size())
977 return false;
979 if (out_value)
980 *out_value = list_[index];
981 else
982 delete list_[index];
984 list_.erase(list_.begin() + index);
985 return true;
988 bool ListValue::Remove(const Value& value, size_t* index) {
989 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) {
990 if ((*i)->Equals(&value)) {
991 size_t previous_index = i - list_.begin();
992 delete *i;
993 list_.erase(i);
995 if (index)
996 *index = previous_index;
997 return true;
1000 return false;
1003 ListValue::iterator ListValue::Erase(iterator iter, Value** out_value) {
1004 if (out_value)
1005 *out_value = *iter;
1006 else
1007 delete *iter;
1009 return list_.erase(iter);
1012 void ListValue::Append(Value* in_value) {
1013 DCHECK(in_value);
1014 list_.push_back(in_value);
1017 void ListValue::AppendBoolean(bool in_value) {
1018 Append(CreateBooleanValue(in_value));
1021 void ListValue::AppendInteger(int in_value) {
1022 Append(CreateIntegerValue(in_value));
1025 void ListValue::AppendDouble(double in_value) {
1026 Append(CreateDoubleValue(in_value));
1029 void ListValue::AppendString(const std::string& in_value) {
1030 Append(CreateStringValue(in_value));
1033 void ListValue::AppendString(const string16& in_value) {
1034 Append(CreateStringValue(in_value));
1037 void ListValue::AppendStrings(const std::vector<std::string>& in_values) {
1038 for (std::vector<std::string>::const_iterator it = in_values.begin();
1039 it != in_values.end(); ++it) {
1040 AppendString(*it);
1044 void ListValue::AppendStrings(const std::vector<string16>& in_values) {
1045 for (std::vector<string16>::const_iterator it = in_values.begin();
1046 it != in_values.end(); ++it) {
1047 AppendString(*it);
1051 bool ListValue::AppendIfNotPresent(Value* in_value) {
1052 DCHECK(in_value);
1053 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) {
1054 if ((*i)->Equals(in_value)) {
1055 delete in_value;
1056 return false;
1059 list_.push_back(in_value);
1060 return true;
1063 bool ListValue::Insert(size_t index, Value* in_value) {
1064 DCHECK(in_value);
1065 if (index > list_.size())
1066 return false;
1068 list_.insert(list_.begin() + index, in_value);
1069 return true;
1072 ListValue::const_iterator ListValue::Find(const Value& value) const {
1073 return std::find_if(list_.begin(), list_.end(), ValueEquals(&value));
1076 void ListValue::Swap(ListValue* other) {
1077 list_.swap(other->list_);
1080 bool ListValue::GetAsList(ListValue** out_value) {
1081 if (out_value)
1082 *out_value = this;
1083 return true;
1086 bool ListValue::GetAsList(const ListValue** out_value) const {
1087 if (out_value)
1088 *out_value = this;
1089 return true;
1092 ListValue* ListValue::DeepCopy() const {
1093 ListValue* result = new ListValue;
1095 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
1096 result->Append((*i)->DeepCopy());
1098 return result;
1101 bool ListValue::Equals(const Value* other) const {
1102 if (other->GetType() != GetType())
1103 return false;
1105 const ListValue* other_list =
1106 static_cast<const ListValue*>(other);
1107 const_iterator lhs_it, rhs_it;
1108 for (lhs_it = begin(), rhs_it = other_list->begin();
1109 lhs_it != end() && rhs_it != other_list->end();
1110 ++lhs_it, ++rhs_it) {
1111 if (!(*lhs_it)->Equals(*rhs_it))
1112 return false;
1114 if (lhs_it != end() || rhs_it != other_list->end())
1115 return false;
1117 return true;
1120 ValueSerializer::~ValueSerializer() {
1123 std::ostream& operator<<(std::ostream& out, const Value& value) {
1124 std::string json;
1125 JSONWriter::WriteWithOptions(&value,
1126 JSONWriter::OPTIONS_PRETTY_PRINT,
1127 &json);
1128 return out << json;
1131 } // namespace base