diff options
author | Jinkun Jang <jinkun.jang@samsung.com> | 2013-03-13 01:41:38 +0900 |
---|---|---|
committer | Jinkun Jang <jinkun.jang@samsung.com> | 2013-03-13 01:41:38 +0900 |
commit | 8a6ea078957a71e285dcf1db46aa1e5d26dfcb3f (patch) | |
tree | ebbbe8a8120031a0a1340161064b1e1a2b2bc2ef /base/values.cc | |
parent | f0b7f23011002ef4a1e455be07c6b298cb5cef94 (diff) | |
download | chromium-8a6ea078957a71e285dcf1db46aa1e5d26dfcb3f.tar.gz chromium-8a6ea078957a71e285dcf1db46aa1e5d26dfcb3f.tar.bz2 chromium-8a6ea078957a71e285dcf1db46aa1e5d26dfcb3f.zip |
Tizen 2.1 base
Diffstat (limited to 'base/values.cc')
-rw-r--r-- | base/values.cc | 905 |
1 files changed, 905 insertions, 0 deletions
diff --git a/base/values.cc b/base/values.cc new file mode 100644 index 000000000000..7a364bd8ff0f --- /dev/null +++ b/base/values.cc @@ -0,0 +1,905 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/values.h" + +#include "base/logging.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" + +namespace { + +// Make a deep copy of |node|, but don't include empty lists or dictionaries +// in the copy. It's possible for this function to return NULL and it +// expects |node| to always be non-NULL. +Value* CopyWithoutEmptyChildren(Value* node) { + DCHECK(node); + switch (node->GetType()) { + case Value::TYPE_LIST: { + ListValue* list = static_cast<ListValue*>(node); + ListValue* copy = new ListValue; + for (ListValue::const_iterator it = list->begin(); it != list->end(); + ++it) { + Value* child_copy = CopyWithoutEmptyChildren(*it); + if (child_copy) + copy->Append(child_copy); + } + if (!copy->empty()) + return copy; + + delete copy; + return NULL; + } + + case Value::TYPE_DICTIONARY: { + DictionaryValue* dict = static_cast<DictionaryValue*>(node); + DictionaryValue* copy = new DictionaryValue; + for (DictionaryValue::key_iterator it = dict->begin_keys(); + it != dict->end_keys(); ++it) { + Value* child = NULL; + bool rv = dict->GetWithoutPathExpansion(*it, &child); + DCHECK(rv); + Value* child_copy = CopyWithoutEmptyChildren(child); + if (child_copy) + copy->SetWithoutPathExpansion(*it, child_copy); + } + if (!copy->empty()) + return copy; + + delete copy; + return NULL; + } + + default: + // For everything else, just make a copy. + return node->DeepCopy(); + } +} + +} // namespace + +namespace base { + +///////////////////// Value //////////////////// + +Value::~Value() { +} + +// static +Value* Value::CreateNullValue() { + return new Value(TYPE_NULL); +} + +// static +FundamentalValue* Value::CreateBooleanValue(bool in_value) { + return new FundamentalValue(in_value); +} + +// static +FundamentalValue* Value::CreateIntegerValue(int in_value) { + return new FundamentalValue(in_value); +} + +// static +FundamentalValue* Value::CreateDoubleValue(double in_value) { + return new FundamentalValue(in_value); +} + +// static +StringValue* Value::CreateStringValue(const std::string& in_value) { + return new StringValue(in_value); +} + +// static +StringValue* Value::CreateStringValue(const string16& in_value) { + return new StringValue(in_value); +} + +bool Value::GetAsBoolean(bool* out_value) const { + return false; +} + +bool Value::GetAsInteger(int* out_value) const { + return false; +} + +bool Value::GetAsDouble(double* out_value) const { + return false; +} + +bool Value::GetAsString(std::string* out_value) const { + return false; +} + +bool Value::GetAsString(string16* out_value) const { + return false; +} + +bool Value::GetAsList(ListValue** out_value) { + return false; +} + +bool Value::GetAsList(const ListValue** out_value) const { + return false; +} + +Value* Value::DeepCopy() const { + // This method should only be getting called for null Values--all subclasses + // need to provide their own implementation;. + DCHECK(IsType(TYPE_NULL)); + return CreateNullValue(); +} + +bool Value::Equals(const Value* other) const { + // This method should only be getting called for null Values--all subclasses + // need to provide their own implementation;. + DCHECK(IsType(TYPE_NULL)); + return other->IsType(TYPE_NULL); +} + +// static +bool Value::Equals(const Value* a, const Value* b) { + if ((a == NULL) && (b == NULL)) return true; + if ((a == NULL) ^ (b == NULL)) return false; + return a->Equals(b); +} + +Value::Value(Type type) : type_(type) { +} + +///////////////////// FundamentalValue //////////////////// + +FundamentalValue::FundamentalValue(bool in_value) + : Value(TYPE_BOOLEAN), boolean_value_(in_value) { +} + +FundamentalValue::FundamentalValue(int in_value) + : Value(TYPE_INTEGER), integer_value_(in_value) { +} + +FundamentalValue::FundamentalValue(double in_value) + : Value(TYPE_DOUBLE), double_value_(in_value) { +} + +FundamentalValue::~FundamentalValue() { +} + +bool FundamentalValue::GetAsBoolean(bool* out_value) const { + if (out_value && IsType(TYPE_BOOLEAN)) + *out_value = boolean_value_; + return (IsType(TYPE_BOOLEAN)); +} + +bool FundamentalValue::GetAsInteger(int* out_value) const { + if (out_value && IsType(TYPE_INTEGER)) + *out_value = integer_value_; + return (IsType(TYPE_INTEGER)); +} + +bool FundamentalValue::GetAsDouble(double* out_value) const { + if (out_value && IsType(TYPE_DOUBLE)) + *out_value = double_value_; + else if (out_value && IsType(TYPE_INTEGER)) + *out_value = integer_value_; + return (IsType(TYPE_DOUBLE) || IsType(TYPE_INTEGER)); +} + +FundamentalValue* FundamentalValue::DeepCopy() const { + switch (GetType()) { + case TYPE_BOOLEAN: + return CreateBooleanValue(boolean_value_); + + case TYPE_INTEGER: + return CreateIntegerValue(integer_value_); + + case TYPE_DOUBLE: + return CreateDoubleValue(double_value_); + + default: + NOTREACHED(); + return NULL; + } +} + +bool FundamentalValue::Equals(const Value* other) const { + if (other->GetType() != GetType()) + return false; + + switch (GetType()) { + case TYPE_BOOLEAN: { + bool lhs, rhs; + return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs; + } + case TYPE_INTEGER: { + int lhs, rhs; + return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs; + } + case TYPE_DOUBLE: { + double lhs, rhs; + return GetAsDouble(&lhs) && other->GetAsDouble(&rhs) && lhs == rhs; + } + default: + NOTREACHED(); + return false; + } +} + +///////////////////// StringValue //////////////////// + +StringValue::StringValue(const std::string& in_value) + : Value(TYPE_STRING), + value_(in_value) { + DCHECK(IsStringUTF8(in_value)); +} + +StringValue::StringValue(const string16& in_value) + : Value(TYPE_STRING), + value_(UTF16ToUTF8(in_value)) { +} + +StringValue::~StringValue() { +} + +bool StringValue::GetAsString(std::string* out_value) const { + if (out_value) + *out_value = value_; + return true; +} + +bool StringValue::GetAsString(string16* out_value) const { + if (out_value) + *out_value = UTF8ToUTF16(value_); + return true; +} + +StringValue* StringValue::DeepCopy() const { + return CreateStringValue(value_); +} + +bool StringValue::Equals(const Value* other) const { + if (other->GetType() != GetType()) + return false; + std::string lhs, rhs; + return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs; +} + +///////////////////// BinaryValue //////////////////// + +BinaryValue::~BinaryValue() { + DCHECK(buffer_); + if (buffer_) + delete[] buffer_; +} + +// static +BinaryValue* BinaryValue::Create(char* buffer, size_t size) { + if (!buffer) + return NULL; + + return new BinaryValue(buffer, size); +} + +// static +BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer, + size_t size) { + if (!buffer) + return NULL; + + char* buffer_copy = new char[size]; + memcpy(buffer_copy, buffer, size); + return new BinaryValue(buffer_copy, size); +} + +BinaryValue* BinaryValue::DeepCopy() const { + return CreateWithCopiedBuffer(buffer_, size_); +} + +bool BinaryValue::Equals(const Value* other) const { + if (other->GetType() != GetType()) + return false; + const BinaryValue* other_binary = static_cast<const BinaryValue*>(other); + if (other_binary->size_ != size_) + return false; + return !memcmp(buffer_, other_binary->buffer_, size_); +} + +BinaryValue::BinaryValue(char* buffer, size_t size) + : Value(TYPE_BINARY), + buffer_(buffer), + size_(size) { + DCHECK(buffer_); +} + +///////////////////// DictionaryValue //////////////////// + +DictionaryValue::DictionaryValue() + : Value(TYPE_DICTIONARY) { +} + +DictionaryValue::~DictionaryValue() { + Clear(); +} + +bool DictionaryValue::HasKey(const std::string& key) const { + DCHECK(IsStringUTF8(key)); + ValueMap::const_iterator current_entry = dictionary_.find(key); + DCHECK((current_entry == dictionary_.end()) || current_entry->second); + return current_entry != dictionary_.end(); +} + +void DictionaryValue::Clear() { + ValueMap::iterator dict_iterator = dictionary_.begin(); + while (dict_iterator != dictionary_.end()) { + delete dict_iterator->second; + ++dict_iterator; + } + + dictionary_.clear(); +} + +void DictionaryValue::Set(const std::string& path, Value* in_value) { + DCHECK(IsStringUTF8(path)); + DCHECK(in_value); + + std::string current_path(path); + DictionaryValue* current_dictionary = this; + for (size_t delimiter_position = current_path.find('.'); + delimiter_position != std::string::npos; + delimiter_position = current_path.find('.')) { + // Assume that we're indexing into a dictionary. + std::string key(current_path, 0, delimiter_position); + DictionaryValue* child_dictionary = NULL; + if (!current_dictionary->GetDictionary(key, &child_dictionary)) { + child_dictionary = new DictionaryValue; + current_dictionary->SetWithoutPathExpansion(key, child_dictionary); + } + + current_dictionary = child_dictionary; + current_path.erase(0, delimiter_position + 1); + } + + current_dictionary->SetWithoutPathExpansion(current_path, in_value); +} + +void DictionaryValue::SetBoolean(const std::string& path, bool in_value) { + Set(path, CreateBooleanValue(in_value)); +} + +void DictionaryValue::SetInteger(const std::string& path, int in_value) { + Set(path, CreateIntegerValue(in_value)); +} + +void DictionaryValue::SetDouble(const std::string& path, double in_value) { + Set(path, CreateDoubleValue(in_value)); +} + +void DictionaryValue::SetString(const std::string& path, + const std::string& in_value) { + Set(path, CreateStringValue(in_value)); +} + +void DictionaryValue::SetString(const std::string& path, + const string16& in_value) { + Set(path, CreateStringValue(in_value)); +} + +void DictionaryValue::SetWithoutPathExpansion(const std::string& key, + Value* in_value) { + // If there's an existing value here, we need to delete it, because + // we own all our children. + if (HasKey(key)) { + DCHECK(dictionary_[key] != in_value); // This would be bogus + delete dictionary_[key]; + } + + dictionary_[key] = in_value; +} + +bool DictionaryValue::Get(const std::string& path, Value** out_value) const { + DCHECK(IsStringUTF8(path)); + std::string current_path(path); + const DictionaryValue* current_dictionary = this; + for (size_t delimiter_position = current_path.find('.'); + delimiter_position != std::string::npos; + delimiter_position = current_path.find('.')) { + DictionaryValue* child_dictionary = NULL; + if (!current_dictionary->GetDictionary( + current_path.substr(0, delimiter_position), &child_dictionary)) + return false; + + current_dictionary = child_dictionary; + current_path.erase(0, delimiter_position + 1); + } + + return current_dictionary->GetWithoutPathExpansion(current_path, out_value); +} + +bool DictionaryValue::GetBoolean(const std::string& path, + bool* bool_value) const { + Value* value; + if (!Get(path, &value)) + return false; + + return value->GetAsBoolean(bool_value); +} + +bool DictionaryValue::GetInteger(const std::string& path, + int* out_value) const { + Value* value; + if (!Get(path, &value)) + return false; + + return value->GetAsInteger(out_value); +} + +bool DictionaryValue::GetDouble(const std::string& path, + double* out_value) const { + Value* value; + if (!Get(path, &value)) + return false; + + return value->GetAsDouble(out_value); +} + +bool DictionaryValue::GetString(const std::string& path, + std::string* out_value) const { + Value* value; + if (!Get(path, &value)) + return false; + + return value->GetAsString(out_value); +} + +bool DictionaryValue::GetString(const std::string& path, + string16* out_value) const { + Value* value; + if (!Get(path, &value)) + return false; + + return value->GetAsString(out_value); +} + +bool DictionaryValue::GetStringASCII(const std::string& path, + std::string* out_value) const { + std::string out; + if (!GetString(path, &out)) + return false; + + if (!IsStringASCII(out)) { + NOTREACHED(); + return false; + } + + out_value->assign(out); + return true; +} + +bool DictionaryValue::GetBinary(const std::string& path, + BinaryValue** out_value) const { + Value* value; + bool result = Get(path, &value); + if (!result || !value->IsType(TYPE_BINARY)) + return false; + + if (out_value) + *out_value = static_cast<BinaryValue*>(value); + + return true; +} + +bool DictionaryValue::GetDictionary(const std::string& path, + DictionaryValue** out_value) const { + Value* value; + bool result = Get(path, &value); + if (!result || !value->IsType(TYPE_DICTIONARY)) + return false; + + if (out_value) + *out_value = static_cast<DictionaryValue*>(value); + + return true; +} + +bool DictionaryValue::GetList(const std::string& path, + ListValue** out_value) const { + Value* value; + bool result = Get(path, &value); + if (!result || !value->IsType(TYPE_LIST)) + return false; + + if (out_value) + *out_value = static_cast<ListValue*>(value); + + return true; +} + +bool DictionaryValue::GetWithoutPathExpansion(const std::string& key, + Value** out_value) const { + DCHECK(IsStringUTF8(key)); + ValueMap::const_iterator entry_iterator = dictionary_.find(key); + if (entry_iterator == dictionary_.end()) + return false; + + Value* entry = entry_iterator->second; + if (out_value) + *out_value = entry; + return true; +} + +bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::string& key, + int* out_value) const { + Value* value; + if (!GetWithoutPathExpansion(key, &value)) + return false; + + return value->GetAsInteger(out_value); +} + +bool DictionaryValue::GetDoubleWithoutPathExpansion(const std::string& key, + double* out_value) const { + Value* value; + if (!GetWithoutPathExpansion(key, &value)) + return false; + + return value->GetAsDouble(out_value); +} + +bool DictionaryValue::GetStringWithoutPathExpansion( + const std::string& key, + std::string* out_value) const { + Value* value; + if (!GetWithoutPathExpansion(key, &value)) + return false; + + return value->GetAsString(out_value); +} + +bool DictionaryValue::GetStringWithoutPathExpansion( + const std::string& key, + string16* out_value) const { + Value* value; + if (!GetWithoutPathExpansion(key, &value)) + return false; + + return value->GetAsString(out_value); +} + +bool DictionaryValue::GetDictionaryWithoutPathExpansion( + const std::string& key, + DictionaryValue** out_value) const { + Value* value; + bool result = GetWithoutPathExpansion(key, &value); + if (!result || !value->IsType(TYPE_DICTIONARY)) + return false; + + if (out_value) + *out_value = static_cast<DictionaryValue*>(value); + + return true; +} + +bool DictionaryValue::GetListWithoutPathExpansion(const std::string& key, + ListValue** out_value) const { + Value* value; + bool result = GetWithoutPathExpansion(key, &value); + if (!result || !value->IsType(TYPE_LIST)) + return false; + + if (out_value) + *out_value = static_cast<ListValue*>(value); + + return true; +} + +bool DictionaryValue::Remove(const std::string& path, Value** out_value) { + DCHECK(IsStringUTF8(path)); + std::string current_path(path); + DictionaryValue* current_dictionary = this; + size_t delimiter_position = current_path.rfind('.'); + if (delimiter_position != std::string::npos) { + if (!GetDictionary(current_path.substr(0, delimiter_position), + ¤t_dictionary)) + return false; + current_path.erase(0, delimiter_position + 1); + } + + return current_dictionary->RemoveWithoutPathExpansion(current_path, + out_value); +} + +bool DictionaryValue::RemoveWithoutPathExpansion(const std::string& key, + Value** out_value) { + DCHECK(IsStringUTF8(key)); + ValueMap::iterator entry_iterator = dictionary_.find(key); + if (entry_iterator == dictionary_.end()) + return false; + + Value* entry = entry_iterator->second; + if (out_value) + *out_value = entry; + else + delete entry; + dictionary_.erase(entry_iterator); + return true; +} + +DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() { + Value* copy = CopyWithoutEmptyChildren(this); + return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue; +} + +void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) { + for (DictionaryValue::key_iterator key(dictionary->begin_keys()); + key != dictionary->end_keys(); ++key) { + Value* merge_value; + if (dictionary->GetWithoutPathExpansion(*key, &merge_value)) { + // Check whether we have to merge dictionaries. + if (merge_value->IsType(Value::TYPE_DICTIONARY)) { + DictionaryValue* sub_dict; + if (GetDictionaryWithoutPathExpansion(*key, &sub_dict)) { + sub_dict->MergeDictionary( + static_cast<const DictionaryValue*>(merge_value)); + continue; + } + } + // All other cases: Make a copy and hook it up. + SetWithoutPathExpansion(*key, merge_value->DeepCopy()); + } + } +} + +DictionaryValue* DictionaryValue::DeepCopy() const { + DictionaryValue* result = new DictionaryValue; + + for (ValueMap::const_iterator current_entry(dictionary_.begin()); + current_entry != dictionary_.end(); ++current_entry) { + result->SetWithoutPathExpansion(current_entry->first, + current_entry->second->DeepCopy()); + } + + return result; +} + +bool DictionaryValue::Equals(const Value* other) const { + if (other->GetType() != GetType()) + return false; + + const DictionaryValue* other_dict = + static_cast<const DictionaryValue*>(other); + key_iterator lhs_it(begin_keys()); + key_iterator rhs_it(other_dict->begin_keys()); + while (lhs_it != end_keys() && rhs_it != other_dict->end_keys()) { + Value* lhs; + Value* rhs; + if (*lhs_it != *rhs_it || + !GetWithoutPathExpansion(*lhs_it, &lhs) || + !other_dict->GetWithoutPathExpansion(*rhs_it, &rhs) || + !lhs->Equals(rhs)) { + return false; + } + ++lhs_it; + ++rhs_it; + } + if (lhs_it != end_keys() || rhs_it != other_dict->end_keys()) + return false; + + return true; +} + +///////////////////// ListValue //////////////////// + +ListValue::ListValue() : Value(TYPE_LIST) { +} + +ListValue::~ListValue() { + Clear(); +} + +void ListValue::Clear() { + for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) + delete *i; + list_.clear(); +} + +bool ListValue::Set(size_t index, Value* in_value) { + if (!in_value) + return false; + + if (index >= list_.size()) { + // Pad out any intermediate indexes with null settings + while (index > list_.size()) + Append(CreateNullValue()); + Append(in_value); + } else { + DCHECK(list_[index] != in_value); + delete list_[index]; + list_[index] = in_value; + } + return true; +} + +bool ListValue::Get(size_t index, Value** out_value) const { + if (index >= list_.size()) + return false; + + if (out_value) + *out_value = list_[index]; + + return true; +} + +bool ListValue::GetBoolean(size_t index, bool* bool_value) const { + Value* value; + if (!Get(index, &value)) + return false; + + return value->GetAsBoolean(bool_value); +} + +bool ListValue::GetInteger(size_t index, int* out_value) const { + Value* value; + if (!Get(index, &value)) + return false; + + return value->GetAsInteger(out_value); +} + +bool ListValue::GetDouble(size_t index, double* out_value) const { + Value* value; + if (!Get(index, &value)) + return false; + + return value->GetAsDouble(out_value); +} + +bool ListValue::GetString(size_t index, std::string* out_value) const { + Value* value; + if (!Get(index, &value)) + return false; + + return value->GetAsString(out_value); +} + +bool ListValue::GetString(size_t index, string16* out_value) const { + Value* value; + if (!Get(index, &value)) + return false; + + return value->GetAsString(out_value); +} + +bool ListValue::GetBinary(size_t index, BinaryValue** out_value) const { + Value* value; + bool result = Get(index, &value); + if (!result || !value->IsType(TYPE_BINARY)) + return false; + + if (out_value) + *out_value = static_cast<BinaryValue*>(value); + + return true; +} + +bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) const { + Value* value; + bool result = Get(index, &value); + if (!result || !value->IsType(TYPE_DICTIONARY)) + return false; + + if (out_value) + *out_value = static_cast<DictionaryValue*>(value); + + return true; +} + +bool ListValue::GetList(size_t index, ListValue** out_value) const { + Value* value; + bool result = Get(index, &value); + if (!result || !value->IsType(TYPE_LIST)) + return false; + + if (out_value) + *out_value = static_cast<ListValue*>(value); + + return true; +} + +bool ListValue::Remove(size_t index, Value** out_value) { + if (index >= list_.size()) + return false; + + if (out_value) + *out_value = list_[index]; + else + delete list_[index]; + + list_.erase(list_.begin() + index); + return true; +} + +bool ListValue::Remove(const Value& value, size_t* index) { + for (ValueVector::iterator i(list_.begin()); i != list_.end(); ++i) { + if ((*i)->Equals(&value)) { + size_t previous_index = i - list_.begin(); + delete *i; + list_.erase(i); + + if (index) + *index = previous_index; + return true; + } + } + return false; +} + +void ListValue::Append(Value* in_value) { + DCHECK(in_value); + list_.push_back(in_value); +} + +bool ListValue::AppendIfNotPresent(Value* in_value) { + DCHECK(in_value); + for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) { + if ((*i)->Equals(in_value)) { + delete in_value; + return false; + } + } + list_.push_back(in_value); + return true; +} + +bool ListValue::Insert(size_t index, Value* in_value) { + DCHECK(in_value); + if (index > list_.size()) + return false; + + list_.insert(list_.begin() + index, in_value); + return true; +} + +bool ListValue::GetAsList(ListValue** out_value) { + if (out_value) + *out_value = this; + return true; +} + +bool ListValue::GetAsList(const ListValue** out_value) const { + if (out_value) + *out_value = this; + return true; +} + +ListValue* ListValue::DeepCopy() const { + ListValue* result = new ListValue; + + for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i) + result->Append((*i)->DeepCopy()); + + return result; +} + +bool ListValue::Equals(const Value* other) const { + if (other->GetType() != GetType()) + return false; + + const ListValue* other_list = + static_cast<const ListValue*>(other); + const_iterator lhs_it, rhs_it; + for (lhs_it = begin(), rhs_it = other_list->begin(); + lhs_it != end() && rhs_it != other_list->end(); + ++lhs_it, ++rhs_it) { + if (!(*lhs_it)->Equals(*rhs_it)) + return false; + } + if (lhs_it != end() || rhs_it != other_list->end()) + return false; + + return true; +} + +ValueSerializer::~ValueSerializer() { +} + +} // namespace base |