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"
9 #include "base/float_util.h"
10 #include "base/logging.h"
11 #include "base/string_util.h"
12 #include "base/utf_string_conversions.h"
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
) {
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();
27 Value
* child_copy
= CopyWithoutEmptyChildren(*it
);
29 copy
->Append(child_copy
);
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
) {
44 bool rv
= dict
->GetWithoutPathExpansion(*it
, &child
);
46 Value
* child_copy
= CopyWithoutEmptyChildren(child
);
48 copy
->SetWithoutPathExpansion(*it
, child_copy
);
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.
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
);
83 ///////////////////// Value ////////////////////
89 Value
* Value::CreateNullValue() {
90 return new Value(TYPE_NULL
);
94 FundamentalValue
* Value::CreateBooleanValue(bool in_value
) {
95 return new FundamentalValue(in_value
);
99 FundamentalValue
* Value::CreateIntegerValue(int in_value
) {
100 return new FundamentalValue(in_value
);
104 FundamentalValue
* Value::CreateDoubleValue(double in_value
) {
105 return new FundamentalValue(in_value
);
109 StringValue
* Value::CreateStringValue(const std::string
& in_value
) {
110 return new StringValue(in_value
);
114 StringValue
* Value::CreateStringValue(const string16
& in_value
) {
115 return new StringValue(in_value
);
118 bool Value::GetAsBoolean(bool* out_value
) const {
122 bool Value::GetAsInteger(int* out_value
) const {
126 bool Value::GetAsDouble(double* out_value
) const {
130 bool Value::GetAsString(std::string
* out_value
) const {
134 bool Value::GetAsString(string16
* out_value
) const {
138 bool Value::GetAsList(ListValue
** out_value
) {
142 bool Value::GetAsList(const ListValue
** out_value
) const {
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
);
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;
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";
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 {
215 return CreateBooleanValue(boolean_value_
);
218 return CreateIntegerValue(integer_value_
);
221 return CreateDoubleValue(double_value_
);
229 bool FundamentalValue::Equals(const Value
* other
) const {
230 if (other
->GetType() != GetType())
236 return GetAsBoolean(&lhs
) && other
->GetAsBoolean(&rhs
) && lhs
== rhs
;
240 return GetAsInteger(&lhs
) && other
->GetAsInteger(&rhs
) && lhs
== rhs
;
244 return GetAsDouble(&lhs
) && other
->GetAsDouble(&rhs
) && lhs
== rhs
;
252 ///////////////////// StringValue ////////////////////
254 StringValue::StringValue(const std::string
& in_value
)
255 : Value(TYPE_STRING
),
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 {
274 bool StringValue::GetAsString(string16
* out_value
) const {
276 *out_value
= UTF8ToUTF16(value_
);
280 StringValue
* StringValue::DeepCopy() const {
281 return CreateStringValue(value_
);
284 bool StringValue::Equals(const Value
* other
) const {
285 if (other
->GetType() != GetType())
287 std::string lhs
, rhs
;
288 return GetAsString(&lhs
) && other
->GetAsString(&rhs
) && lhs
== rhs
;
291 ///////////////////// BinaryValue ////////////////////
293 BinaryValue::~BinaryValue() {
300 BinaryValue
* BinaryValue::Create(char* buffer
, size_t size
) {
304 return new BinaryValue(buffer
, size
);
308 BinaryValue
* BinaryValue::CreateWithCopiedBuffer(const char* buffer
,
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())
325 const BinaryValue
* other_binary
= static_cast<const BinaryValue
*>(other
);
326 if (other_binary
->size_
!= size_
)
328 return !memcmp(buffer_
, other_binary
->buffer_
, size_
);
331 BinaryValue::BinaryValue(char* buffer
, size_t size
)
332 : Value(TYPE_BINARY
),
338 ///////////////////// DictionaryValue ////////////////////
340 DictionaryValue::DictionaryValue()
341 : Value(TYPE_DICTIONARY
) {
344 DictionaryValue::~DictionaryValue() {
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
;
365 void DictionaryValue::Set(const std::string
& path
, Value
* in_value
) {
366 DCHECK(IsStringUTF8(path
));
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
,
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
))
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 {
446 if (!Get(path
, &value
))
449 return value
->GetAsBoolean(bool_value
);
452 bool DictionaryValue::GetInteger(const std::string
& path
,
453 int* out_value
) const {
455 if (!Get(path
, &value
))
458 return value
->GetAsInteger(out_value
);
461 bool DictionaryValue::GetDouble(const std::string
& path
,
462 double* out_value
) const {
464 if (!Get(path
, &value
))
467 return value
->GetAsDouble(out_value
);
470 bool DictionaryValue::GetString(const std::string
& path
,
471 std::string
* out_value
) const {
473 if (!Get(path
, &value
))
476 return value
->GetAsString(out_value
);
479 bool DictionaryValue::GetString(const std::string
& path
,
480 string16
* out_value
) const {
482 if (!Get(path
, &value
))
485 return value
->GetAsString(out_value
);
488 bool DictionaryValue::GetStringASCII(const std::string
& path
,
489 std::string
* out_value
) const {
491 if (!GetString(path
, &out
))
494 if (!IsStringASCII(out
)) {
499 out_value
->assign(out
);
503 bool DictionaryValue::GetBinary(const std::string
& path
,
504 BinaryValue
** out_value
) const {
506 bool result
= Get(path
, &value
);
507 if (!result
|| !value
->IsType(TYPE_BINARY
))
511 *out_value
= static_cast<BinaryValue
*>(value
);
516 bool DictionaryValue::GetDictionary(const std::string
& path
,
517 DictionaryValue
** out_value
) const {
519 bool result
= Get(path
, &value
);
520 if (!result
|| !value
->IsType(TYPE_DICTIONARY
))
524 *out_value
= static_cast<DictionaryValue
*>(value
);
529 bool DictionaryValue::GetList(const std::string
& path
,
530 ListValue
** out_value
) const {
532 bool result
= Get(path
, &value
);
533 if (!result
|| !value
->IsType(TYPE_LIST
))
537 *out_value
= static_cast<ListValue
*>(value
);
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())
549 Value
* entry
= entry_iterator
->second
;
555 bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::string
& key
,
556 int* out_value
) const {
558 if (!GetWithoutPathExpansion(key
, &value
))
561 return value
->GetAsInteger(out_value
);
564 bool DictionaryValue::GetDoubleWithoutPathExpansion(const std::string
& key
,
565 double* out_value
) const {
567 if (!GetWithoutPathExpansion(key
, &value
))
570 return value
->GetAsDouble(out_value
);
573 bool DictionaryValue::GetStringWithoutPathExpansion(
574 const std::string
& key
,
575 std::string
* out_value
) const {
577 if (!GetWithoutPathExpansion(key
, &value
))
580 return value
->GetAsString(out_value
);
583 bool DictionaryValue::GetStringWithoutPathExpansion(
584 const std::string
& key
,
585 string16
* out_value
) const {
587 if (!GetWithoutPathExpansion(key
, &value
))
590 return value
->GetAsString(out_value
);
593 bool DictionaryValue::GetDictionaryWithoutPathExpansion(
594 const std::string
& key
,
595 DictionaryValue
** out_value
) const {
597 bool result
= GetWithoutPathExpansion(key
, &value
);
598 if (!result
|| !value
->IsType(TYPE_DICTIONARY
))
602 *out_value
= static_cast<DictionaryValue
*>(value
);
607 bool DictionaryValue::GetListWithoutPathExpansion(const std::string
& key
,
608 ListValue
** out_value
) const {
610 bool result
= GetWithoutPathExpansion(key
, &value
);
611 if (!result
|| !value
->IsType(TYPE_LIST
))
615 *out_value
= static_cast<ListValue
*>(value
);
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 ¤t_dictionary
))
629 current_path
.erase(0, delimiter_position
+ 1);
632 return current_dictionary
->RemoveWithoutPathExpansion(current_path
,
636 bool DictionaryValue::RemoveWithoutPathExpansion(const std::string
& key
,
638 DCHECK(IsStringUTF8(key
));
639 ValueMap::iterator entry_iterator
= dictionary_
.find(key
);
640 if (entry_iterator
== dictionary_
.end())
643 Value
* entry
= entry_iterator
->second
;
648 dictionary_
.erase(entry_iterator
);
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
) {
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
));
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());
689 bool DictionaryValue::Equals(const Value
* other
) const {
690 if (other
->GetType() != GetType())
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()) {
700 if (*lhs_it
!= *rhs_it
||
701 !GetWithoutPathExpansion(*lhs_it
, &lhs
) ||
702 !other_dict
->GetWithoutPathExpansion(*rhs_it
, &rhs
) ||
709 if (lhs_it
!= end_keys() || rhs_it
!= other_dict
->end_keys())
715 ///////////////////// ListValue ////////////////////
717 ListValue::ListValue() : Value(TYPE_LIST
) {
720 ListValue::~ListValue() {
724 void ListValue::Clear() {
725 for (ValueVector::iterator
i(list_
.begin()); i
!= list_
.end(); ++i
)
730 bool ListValue::Set(size_t index
, Value
* in_value
) {
734 if (index
>= list_
.size()) {
735 // Pad out any intermediate indexes with null settings
736 while (index
> list_
.size())
737 Append(CreateNullValue());
740 DCHECK(list_
[index
] != in_value
);
742 list_
[index
] = in_value
;
747 bool ListValue::Get(size_t index
, Value
** out_value
) const {
748 if (index
>= list_
.size())
752 *out_value
= list_
[index
];
757 bool ListValue::GetBoolean(size_t index
, bool* bool_value
) const {
759 if (!Get(index
, &value
))
762 return value
->GetAsBoolean(bool_value
);
765 bool ListValue::GetInteger(size_t index
, int* out_value
) const {
767 if (!Get(index
, &value
))
770 return value
->GetAsInteger(out_value
);
773 bool ListValue::GetDouble(size_t index
, double* out_value
) const {
775 if (!Get(index
, &value
))
778 return value
->GetAsDouble(out_value
);
781 bool ListValue::GetString(size_t index
, std::string
* out_value
) const {
783 if (!Get(index
, &value
))
786 return value
->GetAsString(out_value
);
789 bool ListValue::GetString(size_t index
, string16
* out_value
) const {
791 if (!Get(index
, &value
))
794 return value
->GetAsString(out_value
);
797 bool ListValue::GetBinary(size_t index
, BinaryValue
** out_value
) const {
799 bool result
= Get(index
, &value
);
800 if (!result
|| !value
->IsType(TYPE_BINARY
))
804 *out_value
= static_cast<BinaryValue
*>(value
);
809 bool ListValue::GetDictionary(size_t index
, DictionaryValue
** out_value
) const {
811 bool result
= Get(index
, &value
);
812 if (!result
|| !value
->IsType(TYPE_DICTIONARY
))
816 *out_value
= static_cast<DictionaryValue
*>(value
);
821 bool ListValue::GetList(size_t index
, ListValue
** out_value
) const {
823 bool result
= Get(index
, &value
);
824 if (!result
|| !value
->IsType(TYPE_LIST
))
828 *out_value
= static_cast<ListValue
*>(value
);
833 bool ListValue::Remove(size_t index
, Value
** out_value
) {
834 if (index
>= list_
.size())
838 *out_value
= list_
[index
];
842 list_
.erase(list_
.begin() + index
);
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();
854 *index
= previous_index
;
861 void ListValue::Append(Value
* in_value
) {
863 list_
.push_back(in_value
);
866 bool ListValue::AppendIfNotPresent(Value
* in_value
) {
868 for (ValueVector::const_iterator
i(list_
.begin()); i
!= list_
.end(); ++i
) {
869 if ((*i
)->Equals(in_value
)) {
874 list_
.push_back(in_value
);
878 bool ListValue::Insert(size_t index
, Value
* in_value
) {
880 if (index
> list_
.size())
883 list_
.insert(list_
.begin() + index
, in_value
);
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
) {
897 bool ListValue::GetAsList(const ListValue
** out_value
) const {
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());
912 bool ListValue::Equals(const Value
* other
) const {
913 if (other
->GetType() != GetType())
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
))
925 if (lhs_it
!= end() || rhs_it
!= other_list
->end())
931 ValueSerializer::~ValueSerializer() {