--- /dev/null
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE-xwalk file.
+
+#include "utils/values.h"
+
+#include <boost/regex.hpp>
+#include <string.h>
+
+#include <algorithm>
+#include <cassert>
+#include <cmath>
+#include <iostream>
+#include <ostream>
+
+#include "utils/utf_converter.h"
+
+namespace common_installer {
+namespace utils {
+
+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(const Value* node) {
+ assert(node);
+ switch (node->GetType()) {
+ case Value::TYPE_LIST: {
+ const ListValue* list = static_cast<const 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 nullptr;
+ }
+
+ case Value::TYPE_DICTIONARY: {
+ const DictionaryValue* dict = static_cast<const DictionaryValue*>(node);
+ DictionaryValue* copy = new DictionaryValue;
+ for (DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
+ Value* child_copy = CopyWithoutEmptyChildren(&it.value());
+ if (child_copy)
+ copy->SetWithoutPathExpansion(it.key(), child_copy);
+ }
+ if (!copy->empty())
+ return copy;
+
+ delete copy;
+ return nullptr;
+ }
+
+ default:
+ // For everything else, just make a copy.
+ return node->DeepCopy();
+ }
+}
+
+// A small functor for comparing Values for std::find_if and similar.
+class ValueEquals {
+ public:
+ // Pass the value against which all consecutive calls of the () operator will
+ // compare their argument to. This Value object must not be destroyed while
+ // the ValueEquals is in use.
+ explicit ValueEquals(const Value* first) : first_(first) { }
+
+ bool operator ()(const Value* second) const {
+ return first_->Equals(second);
+ }
+
+ private:
+ const Value* first_;
+};
+
+} // namespace
+
+Value::~Value() {
+}
+
+// static
+Value* Value::CreateNullValue() {
+ return new Value(TYPE_NULL);
+}
+
+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(std::u16string* out_value) const {
+ return false;
+}
+
+bool Value::GetAsString(const StringValue** out_value) const {
+ return false;
+}
+
+bool Value::GetAsList(ListValue** out_value) {
+ return false;
+}
+
+bool Value::GetAsList(const ListValue** out_value) const {
+ return false;
+}
+
+bool Value::GetAsDictionary(DictionaryValue** out_value) {
+ return false;
+}
+
+bool Value::GetAsDictionary(const DictionaryValue** 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;.
+ assert(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;.
+ assert(IsType(TYPE_NULL));
+ return other->IsType(TYPE_NULL);
+}
+
+// static
+bool Value::Equals(const Value* a, const Value* b) {
+ if ((!a) && (!b)) return true;
+ if ((!a) ^ (!b)) return false;
+ return a->Equals(b);
+}
+
+Value::Value(Type type) : type_(type) {}
+
+Value::Value(const Value& that) : type_(that.type_) {}
+
+Value& Value::operator=(const Value& that) {
+ type_ = that.type_;
+ return *this;
+}
+
+///////////////////// 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) {
+ if (!std::isfinite(double_value_)) {
+ std::cerr << "Non-finite (i.e. NaN or positive/negative infinity) "
+ << "values cannot be represented in JSON";
+ double_value_ = 0.0;
+ }
+}
+
+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 new FundamentalValue(boolean_value_);
+
+ case TYPE_INTEGER:
+ return new FundamentalValue(integer_value_);
+
+ case TYPE_DOUBLE:
+ return new FundamentalValue(double_value_);
+
+ default:
+ std::cerr << "Not reached.\n";
+ return nullptr;
+ }
+}
+
+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:
+ std::cerr << "Not reached.\n";
+ return false;
+ }
+}
+
+///////////////////// StringValue ////////////////////
+
+StringValue::StringValue(const std::string& in_value)
+ : Value(TYPE_STRING),
+ value_(in_value) {
+ assert(utf_converter::IsStringUTF8(in_value));
+}
+
+StringValue::StringValue(const std::u16string& in_value)
+ : Value(TYPE_STRING),
+ value_(utf_converter::UTF16ToUTF8(in_value)) {
+}
+
+StringValue::~StringValue() {
+}
+
+std::string* StringValue::GetString() {
+ return &value_;
+}
+
+const std::string& StringValue::GetString() const {
+ return value_;
+}
+
+bool StringValue::GetAsString(std::string* out_value) const {
+ if (out_value)
+ *out_value = value_;
+ return true;
+}
+
+bool StringValue::GetAsString(std::u16string* out_value) const {
+ if (out_value)
+ *out_value = utf_converter::UTF8ToUTF16(value_);
+ return true;
+}
+
+bool StringValue::GetAsString(const StringValue** out_value) const {
+ if (out_value)
+ *out_value = this;
+ return true;
+}
+
+StringValue* StringValue::DeepCopy() const {
+ return new StringValue(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()
+ : Value(TYPE_BINARY),
+ size_(0) {
+}
+
+BinaryValue::BinaryValue(std::unique_ptr<char[]> buffer, size_t size)
+ : Value(TYPE_BINARY),
+ buffer_(std::move(buffer)),
+ size_(size) {
+}
+
+BinaryValue::~BinaryValue() {
+}
+
+// static
+BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
+ size_t size) {
+ char* buffer_copy = new char[size];
+ memcpy(buffer_copy, buffer, size);
+ std::unique_ptr<char[]> scoped_buffer_copy(buffer_copy);
+ return new BinaryValue(std::move(scoped_buffer_copy), size);
+}
+
+BinaryValue* BinaryValue::DeepCopy() const {
+ return CreateWithCopiedBuffer(buffer_.get(), 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(GetBuffer(), other_binary->GetBuffer(), size_);
+}
+
+///////////////////// DictionaryValue ////////////////////
+
+DictionaryValue::DictionaryValue()
+ : Value(TYPE_DICTIONARY) {
+}
+
+DictionaryValue::~DictionaryValue() {
+ Clear();
+}
+
+bool DictionaryValue::GetAsDictionary(DictionaryValue** out_value) {
+ if (out_value)
+ *out_value = this;
+ return true;
+}
+
+bool DictionaryValue::GetAsDictionary(const DictionaryValue** out_value) const {
+ if (out_value)
+ *out_value = this;
+ return true;
+}
+
+bool DictionaryValue::HasKey(const std::string& key) const {
+ assert(utf_converter::IsStringUTF8(key));
+ ValueMap::const_iterator current_entry = dictionary_.find(key);
+ assert((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) {
+ assert(utf_converter::IsStringUTF8(path));
+ assert(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 = nullptr;
+ 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, new FundamentalValue(in_value));
+}
+
+void DictionaryValue::SetInteger(const std::string& path, int in_value) {
+ Set(path, new FundamentalValue(in_value));
+}
+
+void DictionaryValue::SetDouble(const std::string& path, double in_value) {
+ Set(path, new FundamentalValue(in_value));
+}
+
+void DictionaryValue::SetString(const std::string& path,
+ const std::string& in_value) {
+ Set(path, new StringValue(in_value));
+}
+
+void DictionaryValue::SetString(const std::string& path,
+ const std::u16string& in_value) {
+ Set(path, new StringValue(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.
+ std::pair<ValueMap::iterator, bool> ins_res =
+ dictionary_.insert(std::make_pair(key, in_value));
+ if (!ins_res.second) {
+ assert(ins_res.first->second != in_value);
+ delete ins_res.first->second;
+ ins_res.first->second = in_value;
+ }
+}
+
+void DictionaryValue::SetBooleanWithoutPathExpansion(
+ const std::string& path, bool in_value) {
+ SetWithoutPathExpansion(path, new FundamentalValue(in_value));
+}
+
+void DictionaryValue::SetIntegerWithoutPathExpansion(
+ const std::string& path, int in_value) {
+ SetWithoutPathExpansion(path, new FundamentalValue(in_value));
+}
+
+void DictionaryValue::SetDoubleWithoutPathExpansion(
+ const std::string& path, double in_value) {
+ SetWithoutPathExpansion(path, new FundamentalValue(in_value));
+}
+
+void DictionaryValue::SetStringWithoutPathExpansion(
+ const std::string& path, const std::string& in_value) {
+ SetWithoutPathExpansion(path, new StringValue(in_value));
+}
+
+void DictionaryValue::SetStringWithoutPathExpansion(
+ const std::string& path, const std::u16string& in_value) {
+ SetWithoutPathExpansion(path, new StringValue(in_value));
+}
+
+bool DictionaryValue::Get(const std::string& path,
+ const Value** out_value) const {
+ assert(utf_converter::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('.')) {
+ const DictionaryValue* child_dictionary = nullptr;
+ 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::Get(const std::string& path, Value** out_value) {
+ return static_cast<const DictionaryValue&>(*this).Get(
+ path,
+ const_cast<const Value**>(out_value));
+}
+
+bool DictionaryValue::GetBoolean(const std::string& path,
+ bool* bool_value) const {
+ 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 {
+ 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 {
+ 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 {
+ const Value* value;
+ if (!Get(path, &value))
+ return false;
+
+ return value->GetAsString(out_value);
+}
+
+bool DictionaryValue::GetString(const std::string& path,
+ std::u16string* out_value) const {
+ 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 (!utf_converter::IsStringASCII(out)) {
+ std::cerr << "Not reached.\n";
+ return false;
+ }
+
+ out_value->assign(out);
+ return true;
+}
+
+bool DictionaryValue::GetBinary(const std::string& path,
+ const BinaryValue** out_value) const {
+ const Value* value;
+ bool result = Get(path, &value);
+ if (!result || !value->IsType(TYPE_BINARY))
+ return false;
+
+ if (out_value)
+ *out_value = static_cast<const BinaryValue*>(value);
+
+ return true;
+}
+
+bool DictionaryValue::GetBinary(const std::string& path,
+ BinaryValue** out_value) {
+ return static_cast<const DictionaryValue&>(*this).GetBinary(
+ path,
+ const_cast<const BinaryValue**>(out_value));
+}
+
+bool DictionaryValue::GetDictionary(const std::string& path,
+ const DictionaryValue** out_value) const {
+ const Value* value;
+ bool result = Get(path, &value);
+ if (!result || !value->IsType(TYPE_DICTIONARY))
+ return false;
+
+ if (out_value)
+ *out_value = static_cast<const DictionaryValue*>(value);
+
+ return true;
+}
+
+bool DictionaryValue::GetDictionary(const std::string& path,
+ DictionaryValue** out_value) {
+ return static_cast<const DictionaryValue&>(*this).GetDictionary(
+ path,
+ const_cast<const DictionaryValue**>(out_value));
+}
+
+bool DictionaryValue::GetList(const std::string& path,
+ const ListValue** out_value) const {
+ const Value* value;
+ bool result = Get(path, &value);
+ if (!result || !value->IsType(TYPE_LIST))
+ return false;
+
+ if (out_value)
+ *out_value = static_cast<const ListValue*>(value);
+
+ return true;
+}
+
+bool DictionaryValue::GetList(const std::string& path, ListValue** out_value) {
+ return static_cast<const DictionaryValue&>(*this).GetList(
+ path,
+ const_cast<const ListValue**>(out_value));
+}
+
+bool DictionaryValue::GetWithoutPathExpansion(const std::string& key,
+ const Value** out_value) const {
+ assert(utf_converter::IsStringUTF8(key));
+ ValueMap::const_iterator entry_iterator = dictionary_.find(key);
+ if (entry_iterator == dictionary_.end())
+ return false;
+
+ const Value* entry = entry_iterator->second;
+ if (out_value)
+ *out_value = entry;
+ return true;
+}
+
+bool DictionaryValue::GetWithoutPathExpansion(const std::string& key,
+ Value** out_value) {
+ return static_cast<const DictionaryValue&>(*this).GetWithoutPathExpansion(
+ key,
+ const_cast<const Value**>(out_value));
+}
+
+bool DictionaryValue::GetBooleanWithoutPathExpansion(const std::string& key,
+ bool* out_value) const {
+ const Value* value;
+ if (!GetWithoutPathExpansion(key, &value))
+ return false;
+
+ return value->GetAsBoolean(out_value);
+}
+
+bool DictionaryValue::GetIntegerWithoutPathExpansion(const std::string& key,
+ int* out_value) const {
+ 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 {
+ 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 {
+ const Value* value;
+ if (!GetWithoutPathExpansion(key, &value))
+ return false;
+
+ return value->GetAsString(out_value);
+}
+
+bool DictionaryValue::GetStringWithoutPathExpansion(const std::string& key,
+ std::u16string* out_value) const {
+ const Value* value;
+ if (!GetWithoutPathExpansion(key, &value))
+ return false;
+
+ return value->GetAsString(out_value);
+}
+
+bool DictionaryValue::GetDictionaryWithoutPathExpansion(
+ const std::string& key,
+ const DictionaryValue** out_value) const {
+ const Value* value;
+ bool result = GetWithoutPathExpansion(key, &value);
+ if (!result || !value->IsType(TYPE_DICTIONARY))
+ return false;
+
+ if (out_value)
+ *out_value = static_cast<const DictionaryValue*>(value);
+
+ return true;
+}
+
+bool DictionaryValue::GetDictionaryWithoutPathExpansion(
+ const std::string& key,
+ DictionaryValue** out_value) {
+ const DictionaryValue& const_this =
+ static_cast<const DictionaryValue&>(*this);
+ return const_this.GetDictionaryWithoutPathExpansion(
+ key,
+ const_cast<const DictionaryValue**>(out_value));
+}
+
+bool DictionaryValue::GetListWithoutPathExpansion(
+ const std::string& key,
+ const ListValue** out_value) const {
+ const Value* value;
+ bool result = GetWithoutPathExpansion(key, &value);
+ if (!result || !value->IsType(TYPE_LIST))
+ return false;
+
+ if (out_value)
+ *out_value = static_cast<const ListValue*>(value);
+
+ return true;
+}
+
+bool DictionaryValue::GetListWithoutPathExpansion(const std::string& key,
+ ListValue** out_value) {
+ return
+ static_cast<const DictionaryValue&>(*this).GetListWithoutPathExpansion(
+ key,
+ const_cast<const ListValue**>(out_value));
+}
+
+bool DictionaryValue::Remove(const std::string& path,
+ std::unique_ptr<Value>* out_value) {
+ assert(utf_converter::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, std::unique_ptr<Value>* out_value) {
+ assert(utf_converter::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->reset(entry);
+ else
+ delete entry;
+ dictionary_.erase(entry_iterator);
+ return true;
+}
+
+bool DictionaryValue::RemovePath(const std::string& path,
+ std::unique_ptr<Value>* out_value) {
+ bool result = false;
+ size_t delimiter_position = path.find('.');
+
+ if (delimiter_position == std::string::npos)
+ return RemoveWithoutPathExpansion(path, out_value);
+
+ const std::string subdict_path = path.substr(0, delimiter_position);
+ DictionaryValue* subdict = nullptr;
+ if (!GetDictionary(subdict_path, &subdict))
+ return false;
+ result = subdict->RemovePath(path.substr(delimiter_position + 1),
+ out_value);
+ if (result && subdict->empty())
+ RemoveWithoutPathExpansion(subdict_path, nullptr);
+
+ return result;
+}
+
+DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() const {
+ Value* copy = CopyWithoutEmptyChildren(this);
+ return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue;
+}
+
+void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
+ for (DictionaryValue::Iterator it(*dictionary); !it.IsAtEnd(); it.Advance()) {
+ const Value* merge_value = &it.value();
+ // Check whether we have to merge dictionaries.
+ if (merge_value->IsType(Value::TYPE_DICTIONARY)) {
+ DictionaryValue* sub_dict;
+ if (GetDictionaryWithoutPathExpansion(it.key(), &sub_dict)) {
+ sub_dict->MergeDictionary(
+ static_cast<const DictionaryValue*>(merge_value));
+ continue;
+ }
+ }
+ // All other cases: Make a copy and hook it up.
+ SetWithoutPathExpansion(it.key(), merge_value->DeepCopy());
+ }
+}
+
+void DictionaryValue::Swap(DictionaryValue* other) {
+ dictionary_.swap(other->dictionary_);
+}
+
+DictionaryValue::Iterator::Iterator(const DictionaryValue& target)
+ : target_(target),
+ it_(target.dictionary_.begin()) {}
+
+DictionaryValue::Iterator::~Iterator() {}
+
+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);
+ Iterator lhs_it(*this);
+ Iterator rhs_it(*other_dict);
+ while (!lhs_it.IsAtEnd() && !rhs_it.IsAtEnd()) {
+ if (lhs_it.key() != rhs_it.key() ||
+ !lhs_it.value().Equals(&rhs_it.value())) {
+ return false;
+ }
+ lhs_it.Advance();
+ rhs_it.Advance();
+ }
+ if (!lhs_it.IsAtEnd() || !rhs_it.IsAtEnd())
+ 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 {
+ assert(list_[index] != in_value);
+ delete list_[index];
+ list_[index] = in_value;
+ }
+ return true;
+}
+
+bool ListValue::Get(size_t index, const Value** out_value) const {
+ if (index >= list_.size())
+ return false;
+
+ if (out_value)
+ *out_value = list_[index];
+
+ return true;
+}
+
+bool ListValue::Get(size_t index, Value** out_value) {
+ return static_cast<const ListValue&>(*this).Get(
+ index,
+ const_cast<const Value**>(out_value));
+}
+
+bool ListValue::GetBoolean(size_t index, bool* bool_value) const {
+ const Value* value;
+ if (!Get(index, &value))
+ return false;
+
+ return value->GetAsBoolean(bool_value);
+}
+
+bool ListValue::GetInteger(size_t index, int* out_value) const {
+ const Value* value;
+ if (!Get(index, &value))
+ return false;
+
+ return value->GetAsInteger(out_value);
+}
+
+bool ListValue::GetDouble(size_t index, double* out_value) const {
+ 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 {
+ const Value* value;
+ if (!Get(index, &value))
+ return false;
+
+ return value->GetAsString(out_value);
+}
+
+bool ListValue::GetString(size_t index, std::u16string* out_value) const {
+ const Value* value;
+ if (!Get(index, &value))
+ return false;
+
+ return value->GetAsString(out_value);
+}
+
+bool ListValue::GetBinary(size_t index, const BinaryValue** out_value) const {
+ const Value* value;
+ bool result = Get(index, &value);
+ if (!result || !value->IsType(TYPE_BINARY))
+ return false;
+
+ if (out_value)
+ *out_value = static_cast<const BinaryValue*>(value);
+
+ return true;
+}
+
+bool ListValue::GetBinary(size_t index, BinaryValue** out_value) {
+ return static_cast<const ListValue&>(*this).GetBinary(
+ index,
+ const_cast<const BinaryValue**>(out_value));
+}
+
+bool ListValue::GetDictionary(size_t index,
+ const DictionaryValue** out_value) const {
+ const Value* value;
+ bool result = Get(index, &value);
+ if (!result || !value->IsType(TYPE_DICTIONARY))
+ return false;
+
+ if (out_value)
+ *out_value = static_cast<const DictionaryValue*>(value);
+
+ return true;
+}
+
+bool ListValue::GetDictionary(size_t index, DictionaryValue** out_value) {
+ return static_cast<const ListValue&>(*this).GetDictionary(
+ index,
+ const_cast<const DictionaryValue**>(out_value));
+}
+
+bool ListValue::GetList(size_t index, const ListValue** out_value) const {
+ const Value* value;
+ bool result = Get(index, &value);
+ if (!result || !value->IsType(TYPE_LIST))
+ return false;
+
+ if (out_value)
+ *out_value = static_cast<const ListValue*>(value);
+
+ return true;
+}
+
+bool ListValue::GetList(size_t index, ListValue** out_value) {
+ return static_cast<const ListValue&>(*this).GetList(
+ index,
+ const_cast<const ListValue**>(out_value));
+}
+
+bool ListValue::Remove(size_t index, std::unique_ptr<Value>* out_value) {
+ if (index >= list_.size())
+ return false;
+
+ if (out_value)
+ out_value->reset(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;
+}
+
+ListValue::iterator ListValue::Erase(iterator iter,
+ std::unique_ptr<Value>* out_value) {
+ if (out_value)
+ out_value->reset(*iter);
+ else
+ delete *iter;
+
+ return list_.erase(iter);
+}
+
+void ListValue::Append(Value* in_value) {
+ assert(in_value);
+ list_.push_back(in_value);
+}
+
+void ListValue::AppendBoolean(bool in_value) {
+ Append(new FundamentalValue(in_value));
+}
+
+void ListValue::AppendInteger(int in_value) {
+ Append(new FundamentalValue(in_value));
+}
+
+void ListValue::AppendDouble(double in_value) {
+ Append(new FundamentalValue(in_value));
+}
+
+void ListValue::AppendString(const std::string& in_value) {
+ Append(new StringValue(in_value));
+}
+
+void ListValue::AppendString(const std::u16string& in_value) {
+ Append(new StringValue(in_value));
+}
+
+void ListValue::AppendStrings(const std::vector<std::string>& in_values) {
+ for (std::vector<std::string>::const_iterator it = in_values.begin();
+ it != in_values.end(); ++it) {
+ AppendString(*it);
+ }
+}
+
+void ListValue::AppendStrings(const std::vector<std::u16string>& in_values) {
+ for (std::vector<std::u16string>::const_iterator it = in_values.begin();
+ it != in_values.end(); ++it) {
+ AppendString(*it);
+ }
+}
+
+bool ListValue::AppendIfNotPresent(Value* in_value) {
+ assert(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) {
+ assert(in_value);
+ if (index > list_.size())
+ return false;
+
+ list_.insert(list_.begin() + index, in_value);
+ return true;
+}
+
+ListValue::const_iterator ListValue::Find(const Value& value) const {
+ return std::find_if(list_.begin(), list_.end(), ValueEquals(&value));
+}
+
+void ListValue::Swap(ListValue* other) {
+ list_.swap(other->list_);
+}
+
+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 utils
+} // namespace common_installer
--- /dev/null
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE-xwalk file.
+
+// This file specifies a recursive data storage class called Value intended for
+// storing settings and other persistable data.
+//
+// A Value represents something that can be stored in JSON or passed to/from
+// JavaScript. As such, it is NOT a generalized variant type, since only the
+// types supported by JavaScript/JSON are supported.
+//
+// IN PARTICULAR this means that there is no support for int64 or unsigned
+// numbers. Writing JSON with such types would violate the spec. If you need
+// something like this, either use a double or make a string value containing
+// the number you want.
+
+#ifndef UTILS_VALUES_H_
+#define UTILS_VALUES_H_
+
+#include <stddef.h>
+
+#include <iosfwd>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace common_installer {
+namespace utils {
+
+class DictionaryValue;
+class FundamentalValue;
+class ListValue;
+class StringValue;
+class Value;
+
+typedef std::vector<Value*> ValueVector;
+typedef std::map<std::string, Value*> ValueMap;
+
+// The Value class is the base class for Values. A Value can be instantiated
+// via the Create*Value() factory methods, or by directly creating instances of
+// the subclasses.
+//
+// See the file-level comment above for more information.
+class Value {
+ public:
+ enum Type {
+ TYPE_NULL = 0,
+ TYPE_BOOLEAN,
+ TYPE_INTEGER,
+ TYPE_DOUBLE,
+ TYPE_STRING,
+ TYPE_BINARY,
+ TYPE_DICTIONARY,
+ TYPE_LIST
+ // Note: Do not add more types. See the file-level comment above for why.
+ };
+
+ virtual ~Value();
+
+ static Value* CreateNullValue();
+
+ // Returns the type of the value stored by the current Value object.
+ // Each type will be implemented by only one subclass of Value, so it's
+ // safe to use the Type to determine whether you can cast from
+ // Value* to (Implementing Class)*. Also, a Value object never changes
+ // its type after construction.
+ Type GetType() const { return type_; }
+
+ // Returns true if the current object represents a given type.
+ bool IsType(Type type) const { return type == type_; }
+
+ // These methods allow the convenient retrieval of the contents of the Value.
+ // If the current object can be converted into the given type, the value is
+ // returned through the |out_value| parameter and true is returned;
+ // otherwise, false is returned and |out_value| is unchanged.
+ virtual bool GetAsBoolean(bool* out_value) const;
+ virtual bool GetAsInteger(int* out_value) const;
+ virtual bool GetAsDouble(double* out_value) const;
+ virtual bool GetAsString(std::string* out_value) const;
+ virtual bool GetAsString(std::u16string* out_value) const;
+ virtual bool GetAsString(const StringValue** out_value) const;
+ virtual bool GetAsList(ListValue** out_value);
+ virtual bool GetAsList(const ListValue** out_value) const;
+ virtual bool GetAsDictionary(DictionaryValue** out_value);
+ virtual bool GetAsDictionary(const DictionaryValue** out_value) const;
+ // Note: Do not add more types. See the file-level comment above for why.
+
+ // This creates a deep copy of the entire Value tree, and returns a pointer
+ // to the copy. The caller gets ownership of the copy, of course.
+ //
+ // Subclasses return their own type directly in their overrides;
+ // this works because C++ supports covariant return types.
+ virtual Value* DeepCopy() const;
+
+ // Compares if two Value objects have equal contents.
+ virtual bool Equals(const Value* other) const;
+
+ // Compares if two Value objects have equal contents. Can handle NULLs.
+ // NULLs are considered equal but different from Value::CreateNullValue().
+ static bool Equals(const Value* a, const Value* b);
+
+ protected:
+ // These aren't safe for end-users, but they are useful for subclasses.
+ explicit Value(Type type);
+ Value(const Value& that);
+ Value& operator=(const Value& that);
+
+ private:
+ Type type_;
+};
+
+// FundamentalValue represents the simple fundamental types of values.
+class FundamentalValue : public Value {
+ public:
+ explicit FundamentalValue(bool in_value);
+ explicit FundamentalValue(int in_value);
+ explicit FundamentalValue(double in_value);
+ ~FundamentalValue() override;
+
+ // Overridden from Value:
+ bool GetAsBoolean(bool* out_value) const override;
+ bool GetAsInteger(int* out_value) const override;
+ // Values of both type TYPE_INTEGER and TYPE_DOUBLE can be obtained as
+ // doubles.
+ bool GetAsDouble(double* out_value) const override;
+ FundamentalValue* DeepCopy() const override;
+ bool Equals(const Value* other) const override;
+
+ private:
+ union {
+ bool boolean_value_;
+ int integer_value_;
+ double double_value_;
+ };
+};
+
+class StringValue : public Value {
+ public:
+ // Initializes a StringValue with a UTF-8 narrow character string.
+ explicit StringValue(const std::string& in_value);
+
+ // Initializes a StringValue with a std::u16string.
+ explicit StringValue(const std::u16string& in_value);
+
+ ~StringValue() override;
+
+ // Returns |value_| as a pointer or reference.
+ std::string* GetString();
+ const std::string& GetString() const;
+
+ // Overridden from Value:
+ bool GetAsString(std::string* out_value) const override;
+ bool GetAsString(std::u16string* out_value) const override;
+ bool GetAsString(const StringValue** out_value) const override;
+ StringValue* DeepCopy() const override;
+ bool Equals(const Value* other) const override;
+
+ private:
+ std::string value_;
+};
+
+class BinaryValue: public Value {
+ public:
+ // Creates a BinaryValue with a null buffer and size of 0.
+ BinaryValue();
+
+ // Creates a BinaryValue, taking ownership of the bytes pointed to by
+ // |buffer|.
+ BinaryValue(std::unique_ptr<char[]> buffer, size_t size);
+
+ ~BinaryValue() override;
+
+ // For situations where you want to keep ownership of your buffer, this
+ // factory method creates a new BinaryValue by copying the contents of the
+ // buffer that's passed in.
+ static BinaryValue* CreateWithCopiedBuffer(const char* buffer, size_t size);
+
+ size_t GetSize() const { return size_; }
+
+ // May return NULL.
+ char* GetBuffer() { return buffer_.get(); }
+ const char* GetBuffer() const { return buffer_.get(); }
+
+ // Overridden from Value:
+ BinaryValue* DeepCopy() const override;
+ bool Equals(const Value* other) const override;
+
+ private:
+ std::unique_ptr<char[]> buffer_;
+ size_t size_;
+};
+
+// DictionaryValue provides a key-value dictionary with (optional) "path"
+// parsing for recursive access; see the comment at the top of the file. Keys
+// are |std::string|s and should be UTF-8 encoded.
+class DictionaryValue : public Value {
+ public:
+ DictionaryValue();
+ ~DictionaryValue() override;
+
+ // Overridden from Value:
+ bool GetAsDictionary(DictionaryValue** out_value) override;
+ bool GetAsDictionary(const DictionaryValue** out_value) const override;
+
+ // Returns true if the current dictionary has a value for the given key.
+ bool HasKey(const std::string& key) const;
+
+ // Returns the number of Values in this dictionary.
+ size_t size() const { return dictionary_.size(); }
+
+ // Returns whether the dictionary is empty.
+ bool empty() const { return dictionary_.empty(); }
+
+ // Clears any current contents of this dictionary.
+ void Clear();
+
+ // Sets the Value associated with the given path starting from this object.
+ // A path has the form "<key>" or "<key>.<key>.[...]", where "." indexes
+ // into the next DictionaryValue down. Obviously, "." can't be used
+ // within a key, but there are no other restrictions on keys.
+ // If the key at any step of the way doesn't exist, or exists but isn't
+ // a DictionaryValue, a new DictionaryValue will be created and attached
+ // to the path in that location.
+ // Note that the dictionary takes ownership of the value referenced by
+ // |in_value|, and therefore |in_value| must be non-NULL.
+ void Set(const std::string& path, Value* in_value);
+
+ // Convenience forms of Set(). These methods will replace any existing
+ // value at that path, even if it has a different type.
+ void SetBoolean(const std::string& path, bool in_value);
+ void SetInteger(const std::string& path, int in_value);
+ void SetDouble(const std::string& path, double in_value);
+ void SetString(const std::string& path, const std::string& in_value);
+ void SetString(const std::string& path, const std::u16string& in_value);
+
+ // Like Set(), but without special treatment of '.'. This allows e.g. URLs to
+ // be used as paths.
+ void SetWithoutPathExpansion(const std::string& key, Value* in_value);
+
+ // Convenience forms of SetWithoutPathExpansion().
+ void SetBooleanWithoutPathExpansion(const std::string& path, bool in_value);
+ void SetIntegerWithoutPathExpansion(const std::string& path, int in_value);
+ void SetDoubleWithoutPathExpansion(const std::string& path, double in_value);
+ void SetStringWithoutPathExpansion(const std::string& path,
+ const std::string& in_value);
+ void SetStringWithoutPathExpansion(const std::string& path,
+ const std::u16string& in_value);
+
+ // Gets the Value associated with the given path starting from this object.
+ // A path has the form "<key>" or "<key>.<key>.[...]", where "." indexes
+ // into the next DictionaryValue down. If the path can be resolved
+ // successfully, the value for the last key in the path will be returned
+ // through the |out_value| parameter, and the function will return true.
+ // Otherwise, it will return false and |out_value| will be untouched.
+ // Note that the dictionary always owns the value that's returned.
+ // |out_value| is optional and will only be set if non-NULL.
+ bool Get(const std::string& path, const Value** out_value) const;
+ bool Get(const std::string& path, Value** out_value);
+
+ // These are convenience forms of Get(). The value will be retrieved
+ // and the return value will be true if the path is valid and the value at
+ // the end of the path can be returned in the form specified.
+ // |out_value| is optional and will only be set if non-NULL.
+ bool GetBoolean(const std::string& path, bool* out_value) const;
+ bool GetInteger(const std::string& path, int* out_value) const;
+ // Values of both type TYPE_INTEGER and TYPE_DOUBLE can be obtained as
+ // doubles.
+ bool GetDouble(const std::string& path, double* out_value) const;
+ bool GetString(const std::string& path, std::string* out_value) const;
+ bool GetString(const std::string& path, std::u16string* out_value) const;
+ bool GetStringASCII(const std::string& path, std::string* out_value) const;
+ bool GetBinary(const std::string& path, const BinaryValue** out_value) const;
+ bool GetBinary(const std::string& path, BinaryValue** out_value);
+ bool GetDictionary(const std::string& path,
+ const DictionaryValue** out_value) const;
+ bool GetDictionary(const std::string& path, DictionaryValue** out_value);
+ bool GetList(const std::string& path, const ListValue** out_value) const;
+ bool GetList(const std::string& path, ListValue** out_value);
+
+ // Like Get(), but without special treatment of '.'. This allows e.g. URLs to
+ // be used as paths.
+ bool GetWithoutPathExpansion(const std::string& key,
+ const Value** out_value) const;
+ bool GetWithoutPathExpansion(const std::string& key, Value** out_value);
+ bool GetBooleanWithoutPathExpansion(const std::string& key,
+ bool* out_value) const;
+ bool GetIntegerWithoutPathExpansion(const std::string& key,
+ int* out_value) const;
+ bool GetDoubleWithoutPathExpansion(const std::string& key,
+ double* out_value) const;
+ bool GetStringWithoutPathExpansion(const std::string& key,
+ std::string* out_value) const;
+ bool GetStringWithoutPathExpansion(const std::string& key,
+ std::u16string* out_value) const;
+ bool GetDictionaryWithoutPathExpansion(
+ const std::string& key,
+ const DictionaryValue** out_value) const;
+ bool GetDictionaryWithoutPathExpansion(const std::string& key,
+ DictionaryValue** out_value);
+ bool GetListWithoutPathExpansion(const std::string& key,
+ const ListValue** out_value) const;
+ bool GetListWithoutPathExpansion(const std::string& key,
+ ListValue** out_value);
+
+ // Removes the Value with the specified path from this dictionary (or one
+ // of its child dictionaries, if the path is more than just a local key).
+ // If |out_value| is non-NULL, the removed Value will be passed out via
+ // |out_value|. If |out_value| is NULL, the removed value will be deleted.
+ // This method returns true if |path| is a valid path; otherwise it will
+ // return false and the DictionaryValue object will be unchanged.
+ virtual bool Remove(const std::string& path,
+ std::unique_ptr<Value>* out_value);
+
+ // Like Remove(), but without special treatment of '.'. This allows e.g. URLs
+ // to be used as paths.
+ virtual bool RemoveWithoutPathExpansion(const std::string& key,
+ std::unique_ptr<Value>* out_value);
+
+ // Removes a path, clearing out all dictionaries on |path| that remain empty
+ // after removing the value at |path|.
+ virtual bool RemovePath(const std::string& path,
+ std::unique_ptr<Value>* out_value);
+
+ // Makes a copy of |this| but doesn't include empty dictionaries and lists in
+ // the copy. This never returns NULL, even if |this| itself is empty.
+ DictionaryValue* DeepCopyWithoutEmptyChildren() const;
+
+ // Merge |dictionary| into this dictionary. This is done recursively, i.e. any
+ // sub-dictionaries will be merged as well. In case of key collisions, the
+ // passed in dictionary takes precedence and data already present will be
+ // replaced. Values within |dictionary| are deep-copied, so |dictionary| may
+ // be freed any time after this call.
+ void MergeDictionary(const DictionaryValue* dictionary);
+
+ // Swaps contents with the |other| dictionary.
+ virtual void Swap(DictionaryValue* other);
+
+ // This class provides an iterator over both keys and values in the
+ // dictionary. It can't be used to modify the dictionary.
+ class Iterator {
+ public:
+ explicit Iterator(const DictionaryValue& target);
+ ~Iterator();
+
+ bool IsAtEnd() const { return it_ == target_.dictionary_.end(); }
+ void Advance() { ++it_; }
+
+ const std::string& key() const { return it_->first; }
+ const Value& value() const { return *it_->second; }
+
+ private:
+ const DictionaryValue& target_;
+ ValueMap::const_iterator it_;
+ };
+
+ // Overridden from Value:
+ DictionaryValue* DeepCopy() const override;
+ bool Equals(const Value* other) const override;
+
+ private:
+ ValueMap dictionary_;
+};
+
+// This type of Value represents a list of other Value values.
+class ListValue : public Value {
+ public:
+ typedef ValueVector::iterator iterator;
+ typedef ValueVector::const_iterator const_iterator;
+
+ ListValue();
+ ~ListValue() override;
+
+ // Clears the contents of this ListValue
+ void Clear();
+
+ // Returns the number of Values in this list.
+ size_t GetSize() const { return list_.size(); }
+
+ // Returns whether the list is empty.
+ bool empty() const { return list_.empty(); }
+
+ // Sets the list item at the given index to be the Value specified by
+ // the value given. If the index beyond the current end of the list, null
+ // Values will be used to pad out the list.
+ // Returns true if successful, or false if the index was negative or
+ // the value is a null pointer.
+ bool Set(size_t index, Value* in_value);
+
+ // Gets the Value at the given index. Modifies |out_value| (and returns true)
+ // only if the index falls within the current list range.
+ // Note that the list always owns the Value passed out via |out_value|.
+ // |out_value| is optional and will only be set if non-NULL.
+ bool Get(size_t index, const Value** out_value) const;
+ bool Get(size_t index, Value** out_value);
+
+ // Convenience forms of Get(). Modifies |out_value| (and returns true)
+ // only if the index is valid and the Value at that index can be returned
+ // in the specified form.
+ // |out_value| is optional and will only be set if non-NULL.
+ bool GetBoolean(size_t index, bool* out_value) const;
+ bool GetInteger(size_t index, int* out_value) const;
+ // Values of both type TYPE_INTEGER and TYPE_DOUBLE can be obtained as
+ // doubles.
+ bool GetDouble(size_t index, double* out_value) const;
+ bool GetString(size_t index, std::string* out_value) const;
+ bool GetString(size_t index, std::u16string* out_value) const;
+ bool GetBinary(size_t index, const BinaryValue** out_value) const;
+ bool GetBinary(size_t index, BinaryValue** out_value);
+ bool GetDictionary(size_t index, const DictionaryValue** out_value) const;
+ bool GetDictionary(size_t index, DictionaryValue** out_value);
+ bool GetList(size_t index, const ListValue** out_value) const;
+ bool GetList(size_t index, ListValue** out_value);
+
+ // Removes the Value with the specified index from this list.
+ // If |out_value| is non-NULL, the removed Value AND ITS OWNERSHIP will be
+ // passed out via |out_value|. If |out_value| is NULL, the removed value will
+ // be deleted. This method returns true if |index| is valid; otherwise
+ // it will return false and the ListValue object will be unchanged.
+ virtual bool Remove(size_t index, std::unique_ptr<Value>* out_value);
+
+ // Removes the first instance of |value| found in the list, if any, and
+ // deletes it. |index| is the location where |value| was found. Returns false
+ // if not found.
+ bool Remove(const Value& value, size_t* index);
+
+ // Removes the element at |iter|. If |out_value| is NULL, the value will be
+ // deleted, otherwise ownership of the value is passed back to the caller.
+ // Returns an iterator pointing to the location of the element that
+ // followed the erased element.
+ iterator Erase(iterator iter, std::unique_ptr<Value>* out_value);
+
+ // Appends a Value to the end of the list.
+ void Append(Value* in_value);
+
+ // Convenience forms of Append.
+ void AppendBoolean(bool in_value);
+ void AppendInteger(int in_value);
+ void AppendDouble(double in_value);
+ void AppendString(const std::string& in_value);
+ void AppendString(const std::u16string& in_value);
+ void AppendStrings(const std::vector<std::string>& in_values);
+ void AppendStrings(const std::vector<std::u16string>& in_values);
+
+ // Appends a Value if it's not already present. Takes ownership of the
+ // |in_value|. Returns true if successful, or false if the value was already
+ // present. If the value was already present the |in_value| is deleted.
+ bool AppendIfNotPresent(Value* in_value);
+
+ // Insert a Value at index.
+ // Returns true if successful, or false if the index was out of range.
+ bool Insert(size_t index, Value* in_value);
+
+ // Searches for the first instance of |value| in the list using the Equals
+ // method of the Value type.
+ // Returns a const_iterator to the found item or to end() if none exists.
+ const_iterator Find(const Value& value) const;
+
+ // Swaps contents with the |other| list.
+ virtual void Swap(ListValue* other);
+
+ // Iteration.
+ iterator begin() { return list_.begin(); }
+ iterator end() { return list_.end(); }
+
+ const_iterator begin() const { return list_.begin(); }
+ const_iterator end() const { return list_.end(); }
+
+ // Overridden from Value:
+ bool GetAsList(ListValue** out_value) override;
+ bool GetAsList(const ListValue** out_value) const override;
+ ListValue* DeepCopy() const override;
+ bool Equals(const Value* other) const override;
+
+ private:
+ ValueVector list_;
+};
+
+// This interface is implemented by classes that know how to serialize and
+// deserialize Value objects.
+class ValueSerializer {
+ public:
+ virtual ~ValueSerializer();
+
+ virtual bool Serialize(const Value& root) = 0;
+
+ // This method deserializes the subclass-specific format into a Value object.
+ // If the return value is non-NULL, the caller takes ownership of returned
+ // Value. If the return value is NULL, and if error_code is non-NULL,
+ // error_code will be set with the underlying error.
+ // If |error_message| is non-null, it will be filled in with a formatted
+ // error message including the location of the error if appropriate.
+ virtual Value* Deserialize(int* error_code, std::string* error_str) = 0;
+};
+
+} // namespace utils
+} // namespace common_installer
+
+#endif // UTILS_VALUES_H_