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/logging.h"
8 #include "base/string_util.h"
9 #include "base/utf_string_conversions.h"
13 // Make a deep copy of |node|, but don't include empty lists or dictionaries
14 // in the copy. It's possible for this function to return NULL and it
15 // expects |node| to always be non-NULL.
16 Value* CopyWithoutEmptyChildren(Value* node) {
18 switch (node->GetType()) {
19 case Value::TYPE_LIST: {
20 ListValue* list = static_cast<ListValue*>(node);
21 ListValue* copy = new ListValue;
22 for (ListValue::const_iterator it = list->begin(); it != list->end();
24 Value* child_copy = CopyWithoutEmptyChildren(*it);
26 copy->Append(child_copy);
35 case Value::TYPE_DICTIONARY: {
36 DictionaryValue* dict = static_cast<DictionaryValue*>(node);
37 DictionaryValue* copy = new DictionaryValue;
38 for (DictionaryValue::key_iterator it = dict->begin_keys();
39 it != dict->end_keys(); ++it) {
41 bool rv = dict->GetWithoutPathExpansion(*it, &child);
43 Value* child_copy = CopyWithoutEmptyChildren(child);
45 copy->SetWithoutPathExpansion(*it, child_copy);
55 // For everything else, just make a copy.
56 return node->DeepCopy();
64 ///////////////////// Value ////////////////////
70 Value* Value::CreateNullValue() {
71 return new Value(TYPE_NULL);
75 FundamentalValue* Value::CreateBooleanValue(bool in_value) {
76 return new FundamentalValue(in_value);
80 FundamentalValue* Value::CreateIntegerValue(int in_value) {
81 return new FundamentalValue(in_value);
85 FundamentalValue* Value::CreateDoubleValue(double in_value) {
86 return new FundamentalValue(in_value);
90 StringValue* Value::CreateStringValue(const std::string& in_value) {
91 return new StringValue(in_value);
95 StringValue* Value::CreateStringValue(const string16& in_value) {
96 return new StringValue(in_value);
99 bool Value::GetAsBoolean(bool* out_value) const {
103 bool Value::GetAsInteger(int* out_value) const {
107 bool Value::GetAsDouble(double* out_value) const {
111 bool Value::GetAsString(std::string* out_value) const {
115 bool Value::GetAsString(string16* out_value) const {
119 bool Value::GetAsList(ListValue** out_value) {
123 bool Value::GetAsList(const ListValue** out_value) const {
127 Value* Value::DeepCopy() const {
128 // This method should only be getting called for null Values--all subclasses
129 // need to provide their own implementation;.
130 DCHECK(IsType(TYPE_NULL));
131 return CreateNullValue();
134 bool Value::Equals(const Value* other) const {
135 // This method should only be getting called for null Values--all subclasses
136 // need to provide their own implementation;.
137 DCHECK(IsType(TYPE_NULL));
138 return other->IsType(TYPE_NULL);
142 bool Value::Equals(const Value* a, const Value* b) {
143 if ((a == NULL) && (b == NULL)) return true;
144 if ((a == NULL) ^ (b == NULL)) return false;
148 Value::Value(Type type) : type_(type) {
151 ///////////////////// FundamentalValue ////////////////////
153 FundamentalValue::FundamentalValue(bool in_value)
154 : Value(TYPE_BOOLEAN), boolean_value_(in_value) {
157 FundamentalValue::FundamentalValue(int in_value)
158 : Value(TYPE_INTEGER), integer_value_(in_value) {
161 FundamentalValue::FundamentalValue(double in_value)
162 : Value(TYPE_DOUBLE), double_value_(in_value) {
165 FundamentalValue::~FundamentalValue() {
168 bool FundamentalValue::GetAsBoolean(bool* out_value) const {
169 if (out_value && IsType(TYPE_BOOLEAN))
170 *out_value = boolean_value_;
171 return (IsType(TYPE_BOOLEAN));
174 bool FundamentalValue::GetAsInteger(int* out_value) const {
175 if (out_value && IsType(TYPE_INTEGER))
176 *out_value = integer_value_;
177 return (IsType(TYPE_INTEGER));
180 bool FundamentalValue::GetAsDouble(double* out_value) const {
181 if (out_value && IsType(TYPE_DOUBLE))
182 *out_value = double_value_;
183 else if (out_value && IsType(TYPE_INTEGER))
184 *out_value = integer_value_;
185 return (IsType(TYPE_DOUBLE) || IsType(TYPE_INTEGER));
188 FundamentalValue* FundamentalValue::DeepCopy() const {
191 return CreateBooleanValue(boolean_value_);
194 return CreateIntegerValue(integer_value_);
197 return CreateDoubleValue(double_value_);
205 bool FundamentalValue::Equals(const Value* other) const {
206 if (other->GetType() != GetType())
212 return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs;
216 return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs;
220 return GetAsDouble(&lhs) && other->GetAsDouble(&rhs) && lhs == rhs;
228 ///////////////////// StringValue ////////////////////
230 StringValue::StringValue(const std::string& in_value)
231 : Value(TYPE_STRING),
233 DCHECK(IsStringUTF8(in_value));
236 StringValue::StringValue(const string16& in_value)
237 : Value(TYPE_STRING),
238 value_(UTF16ToUTF8(in_value)) {
241 StringValue::~StringValue() {
244 bool StringValue::GetAsString(std::string* out_value) const {
250 bool StringValue::GetAsString(string16* out_value) const {
252 *out_value = UTF8ToUTF16(value_);
256 StringValue* StringValue::DeepCopy() const {
257 return CreateStringValue(value_);
260 bool StringValue::Equals(const Value* other) const {
261 if (other->GetType() != GetType())
263 std::string lhs, rhs;
264 return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
267 ///////////////////// BinaryValue ////////////////////
269 BinaryValue::~BinaryValue() {
276 BinaryValue* BinaryValue::Create(char* buffer, size_t size) {
280 return new BinaryValue(buffer, size);
284 BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
289 char* buffer_copy = new char[size];
290 memcpy(buffer_copy, buffer, size);
291 return new BinaryValue(buffer_copy, size);
294 BinaryValue* BinaryValue::DeepCopy() const {
295 return CreateWithCopiedBuffer(buffer_, size_);
298 bool BinaryValue::Equals(const Value* other) const {
299 if (other->GetType() != GetType())
301 const BinaryValue* other_binary = static_cast<const BinaryValue*>(other);
302 if (other_binary->size_ != size_)
304 return !memcmp(buffer_, other_binary->buffer_, size_);
307 BinaryValue::BinaryValue(char* buffer, size_t size)
308 : Value(TYPE_BINARY),
314 ///////////////////// DictionaryValue ////////////////////
316 DictionaryValue::DictionaryValue()
317 : Value(TYPE_DICTIONARY) {
320 DictionaryValue::~DictionaryValue() {
324 bool DictionaryValue::HasKey(const std::string& key) const {
325 DCHECK(IsStringUTF8(key));
326 ValueMap::const_iterator current_entry = dictionary_.find(key);
327 DCHECK((current_entry == dictionary_.end()) || current_entry->second);
328 return current_entry != dictionary_.end();
331 void DictionaryValue::Clear() {
332 ValueMap::iterator dict_iterator = dictionary_.begin();
333 while (dict_iterator != dictionary_.end()) {
334 delete dict_iterator->second;
341 void DictionaryValue::Set(const std::string& path, Value* in_value) {
342 DCHECK(IsStringUTF8(path));
345 std::string current_path(path);
346 DictionaryValue* current_dictionary = this;
347 for (size_t delimiter_position = current_path.find('.');
348 delimiter_position != std::string::npos;
349 delimiter_position = current_path.find('.')) {
350 // Assume that we're indexing into a dictionary.
351 std::string key(current_path, 0, delimiter_position);
352 DictionaryValue* child_dictionary = NULL;
353 if (!current_dictionary->GetDictionary(key, &child_dictionary)) {
354 child_dictionary = new DictionaryValue;
355 current_dictionary->SetWithoutPathExpansion(key, child_dictionary);
358 current_dictionary = child_dictionary;
359 current_path.erase(0, delimiter_position + 1);
362 current_dictionary->SetWithoutPathExpansion(current_path, in_value);
365 void DictionaryValue::SetBoolean(const std::string& path, bool in_value) {
366 Set(path, CreateBooleanValue(in_value));
369 void DictionaryValue::SetInteger(const std::string& path, int in_value) {
370 Set(path, CreateIntegerValue(in_value));
373 void DictionaryValue::SetDouble(const std::string& path, double in_value) {
374 Set(path, CreateDoubleValue(in_value));
377 void DictionaryValue::SetString(const std::string& path,
378 const std::string& in_value) {
379 Set(path, CreateStringValue(in_value));
382 void DictionaryValue::SetString(const std::string& path,
383 const string16& in_value) {
384 Set(path, CreateStringValue(in_value));
387 void DictionaryValue::SetWithoutPathExpansion(const std::string& key,
389 // If there's an existing value here, we need to delete it, because
390 // we own all our children.
392 DCHECK(dictionary_[key] != in_value); // This would be bogus
393 delete dictionary_[key];
396 dictionary_[key] = in_value;
399 bool DictionaryValue::Get(const std::string& path, Value** out_value) const {
400 DCHECK(IsStringUTF8(path));
401 std::string current_path(path);
402 const DictionaryValue* current_dictionary = this;
403 for (size_t delimiter_position = current_path.find('.');
404 delimiter_position != std::string::npos;
405 delimiter_position = current_path.find('.')) {
406 DictionaryValue* child_dictionary = NULL;
407 if (!current_dictionary->GetDictionary(
408 current_path.substr(0, delimiter_position), &child_dictionary))
411 current_dictionary = child_dictionary;
412 current_path.erase(0, delimiter_position + 1);
415 return current_dictionary->GetWithoutPathExpansion(current_path, out_value);
418 bool DictionaryValue::GetBoolean(const std::string& path,
419 bool* bool_value) const {
421 if (!Get(path, &value))
424 return value->GetAsBoolean(bool_value);
427 bool DictionaryValue::GetInteger(const std::string& path,
428 int* out_value) const {
430 if (!Get(path, &value))
433 return value->GetAsInteger(out_value);
436 bool DictionaryValue::GetDouble(const std::string& path,
437 double* out_value) const {
439 if (!Get(path, &value))
442 return value->GetAsDouble(out_value);
445 bool DictionaryValue::GetString(const std::string& path,
446 std::string* out_value) const {
448 if (!Get(path, &value))
451 return value->GetAsString(out_value);
454 bool DictionaryValue::GetString(const std::string& path,
455 string16* out_value) const {
457 if (!Get(path, &value))
460 return value->GetAsString(out_value);
463 bool DictionaryValue::GetStringASCII(const std::string& path,
464 std::string* out_value) const {
466 if (!GetString(path, &out))
469 if (!IsStringASCII(out)) {
474 out_value->assign(out);
478 bool DictionaryValue::GetBinary(const std::string& path,
479 BinaryValue** out_value) const {
481 bool result = Get(path, &value);
482 if (!result || !value->IsType(TYPE_BINARY))
486 *out_value = static_cast<BinaryValue*>(value);
491 bool DictionaryValue::GetDictionary(const std::string& path,
492 DictionaryValue** out_value) const {
494 bool result = Get(path, &value);
495 if (!result || !value->IsType(TYPE_DICTIONARY))
499 *out_value = static_cast<DictionaryValue*>(value);
504 bool DictionaryValue::GetList(const std::string& path,
505 ListValue** out_value) const {
507 bool result = Get(path, &value);
508 if (!result || !value->IsType(TYPE_LIST))
512 *out_value = static_cast<ListValue*>(value);
517 bool DictionaryValue::GetWithoutPathExpansion(const std::string& key,
518 Value** out_value) const {
519 DCHECK(IsStringUTF8(key));
520 ValueMap::const_iterator entry_iterator = dictionary_.find(key);
521 if (entry_iterator == dictionary_.end())
524 Value* entry = entry_iterator->second;
530 bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::string& key,
531 int* out_value) const {
533 if (!GetWithoutPathExpansion(key, &value))
536 return value->GetAsInteger(out_value);
539 bool DictionaryValue::GetDoubleWithoutPathExpansion(const std::string& key,
540 double* out_value) const {
542 if (!GetWithoutPathExpansion(key, &value))
545 return value->GetAsDouble(out_value);
548 bool DictionaryValue::GetStringWithoutPathExpansion(
549 const std::string& key,
550 std::string* out_value) const {
552 if (!GetWithoutPathExpansion(key, &value))
555 return value->GetAsString(out_value);
558 bool DictionaryValue::GetStringWithoutPathExpansion(
559 const std::string& key,
560 string16* out_value) const {
562 if (!GetWithoutPathExpansion(key, &value))
565 return value->GetAsString(out_value);
568 bool DictionaryValue::GetDictionaryWithoutPathExpansion(
569 const std::string& key,
570 DictionaryValue** out_value) const {
572 bool result = GetWithoutPathExpansion(key, &value);
573 if (!result || !value->IsType(TYPE_DICTIONARY))
577 *out_value = static_cast<DictionaryValue*>(value);
582 bool DictionaryValue::GetListWithoutPathExpansion(const std::string& key,
583 ListValue** out_value) const {
585 bool result = GetWithoutPathExpansion(key, &value);
586 if (!result || !value->IsType(TYPE_LIST))
590 *out_value = static_cast<ListValue*>(value);
595 bool DictionaryValue::Remove(const std::string& path, Value** out_value) {
596 DCHECK(IsStringUTF8(path));
597 std::string current_path(path);
598 DictionaryValue* current_dictionary = this;
599 size_t delimiter_position = current_path.rfind('.');
600 if (delimiter_position != std::string::npos) {
601 if (!GetDictionary(current_path.substr(0, delimiter_position),
602 ¤t_dictionary))
604 current_path.erase(0, delimiter_position + 1);
607 return current_dictionary->RemoveWithoutPathExpansion(current_path,
611 bool DictionaryValue::RemoveWithoutPathExpansion(const std::string& key,
613 DCHECK(IsStringUTF8(key));
614 ValueMap::iterator entry_iterator = dictionary_.find(key);
615 if (entry_iterator == dictionary_.end())
618 Value* entry = entry_iterator->second;
623 dictionary_.erase(entry_iterator);
627 DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() {
628 Value* copy = CopyWithoutEmptyChildren(this);
629 return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue;
632 void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
633 for (DictionaryValue::key_iterator key(dictionary->begin_keys());
634 key != dictionary->end_keys(); ++key) {
636 if (dictionary->GetWithoutPathExpansion(*key, &merge_value)) {
637 // Check whether we have to merge dictionaries.
638 if (merge_value->IsType(Value::TYPE_DICTIONARY)) {
639 DictionaryValue* sub_dict;
640 if (GetDictionaryWithoutPathExpansion(*key, &sub_dict)) {
641 sub_dict->MergeDictionary(
642 static_cast<const DictionaryValue*>(merge_value));
646 // All other cases: Make a copy and hook it up.
647 SetWithoutPathExpansion(*key, merge_value->DeepCopy());
652 DictionaryValue* DictionaryValue::DeepCopy() const {
653 DictionaryValue* result = new DictionaryValue;
655 for (ValueMap::const_iterator current_entry(dictionary_.begin());
656 current_entry != dictionary_.end(); ++current_entry) {
657 result->SetWithoutPathExpansion(current_entry->first,
658 current_entry->second->DeepCopy());
664 bool DictionaryValue::Equals(const Value* other) const {
665 if (other->GetType() != GetType())
668 const DictionaryValue* other_dict =
669 static_cast<const DictionaryValue*>(other);
670 key_iterator lhs_it(begin_keys());
671 key_iterator rhs_it(other_dict->begin_keys());
672 while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) {
675 if (*lhs_it != *rhs_it ||
676 !GetWithoutPathExpansion(*lhs_it, &lhs) ||
677 !other_dict->GetWithoutPathExpansion(*rhs_it, &rhs) ||
684 if (lhs_it != end_keys() || rhs_it != other_dict->end_keys())
690 ///////////////////// ListValue ////////////////////
692 ListValue::ListValue() : Value(TYPE_LIST) {
695 ListValue::~ListValue() {
699 void ListValue::Clear() {
700 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i)
705 bool ListValue::Set(size_t index, Value* in_value) {
709 if (index >= list_.size()) {
710 // Pad out any intermediate indexes with null settings
711 while (index > list_.size())
712 Append(CreateNullValue());
715 DCHECK(list_[index] != in_value);
717 list_[index] = in_value;
722 bool ListValue::Get(size_t index, Value** out_value) const {
723 if (index >= list_.size())
727 *out_value = list_[index];
732 bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
734 if (!Get(index, &value))
737 return value->GetAsBoolean(bool_value);
740 bool ListValue::GetInteger(size_t index, int* out_value) const {
742 if (!Get(index, &value))
745 return value->GetAsInteger(out_value);
748 bool ListValue::GetDouble(size_t index, double* out_value) const {
750 if (!Get(index, &value))
753 return value->GetAsDouble(out_value);
756 bool ListValue::GetString(size_t index, std::string* out_value) const {
758 if (!Get(index, &value))
761 return value->GetAsString(out_value);
764 bool ListValue::GetString(size_t index, string16* out_value) const {
766 if (!Get(index, &value))
769 return value->GetAsString(out_value);
772 bool ListValue::GetBinary(size_t index, BinaryValue** out_value) const {
774 bool result = Get(index, &value);
775 if (!result || !value->IsType(TYPE_BINARY))
779 *out_value = static_cast<BinaryValue*>(value);
784 bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) const {
786 bool result = Get(index, &value);
787 if (!result || !value->IsType(TYPE_DICTIONARY))
791 *out_value = static_cast<DictionaryValue*>(value);
796 bool ListValue::GetList(size_t index, ListValue** out_value) const {
798 bool result = Get(index, &value);
799 if (!result || !value->IsType(TYPE_LIST))
803 *out_value = static_cast<ListValue*>(value);
808 bool ListValue::Remove(size_t index, Value** out_value) {
809 if (index >= list_.size())
813 *out_value = list_[index];
817 list_.erase(list_.begin() + index);
821 bool ListValue::Remove(const Value& value, size_t* index) {
822 for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) {
823 if ((*i)->Equals(&value)) {
824 size_t previous_index = i - list_.begin();
829 *index = previous_index;
836 void ListValue::Append(Value* in_value) {
838 list_.push_back(in_value);
841 bool ListValue::AppendIfNotPresent(Value* in_value) {
843 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) {
844 if ((*i)->Equals(in_value)) {
849 list_.push_back(in_value);
853 bool ListValue::Insert(size_t index, Value* in_value) {
855 if (index > list_.size())
858 list_.insert(list_.begin() + index, in_value);
862 bool ListValue::GetAsList(ListValue** out_value) {
868 bool ListValue::GetAsList(const ListValue** out_value) const {
874 ListValue* ListValue::DeepCopy() const {
875 ListValue* result = new ListValue;
877 for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
878 result->Append((*i)->DeepCopy());
883 bool ListValue::Equals(const Value* other) const {
884 if (other->GetType() != GetType())
887 const ListValue* other_list =
888 static_cast<const ListValue*>(other);
889 const_iterator lhs_it, rhs_it;
890 for (lhs_it = begin(), rhs_it = other_list->begin();
891 lhs_it != end() && rhs_it != other_list->end();
892 ++lhs_it, ++rhs_it) {
893 if (!(*lhs_it)->Equals(*rhs_it))
896 if (lhs_it != end() || rhs_it != other_list->end())
902 ValueSerializer::~ValueSerializer() {