Add utils library. 24/34824/4
authorJakub Izydorczyk <j.izydorczyk@samsung.com>
Fri, 23 Jan 2015 13:09:51 +0000 (14:09 +0100)
committerJakub Izydorczyk <j.izydorczyk@samsung.com>
Fri, 6 Feb 2015 08:13:38 +0000 (09:13 +0100)
It is supposed to contain common utilities, which can be used by
other parts of code. This commit contains utf_converter code,
which allows convertions between std::u16string and std::string.
There is also DictionaryValue class added, which is needed for
saving nodes of widget manifest.

Change-Id: Ibe4265e6dc3a7f78637d0103222d87d16b70bc2a

CMakeLists.txt
packaging/app-installers.spec
src/CMakeLists.txt
src/utils/CMakeLists.txt [new file with mode: 0644]
src/utils/utf_converter.cc [new file with mode: 0644]
src/utils/utf_converter.h [new file with mode: 0644]
src/utils/values.cc [new file with mode: 0644]
src/utils/values.h [new file with mode: 0644]

index 22f9180..66bad10 100644 (file)
@@ -23,6 +23,7 @@ SET(CMAKE_CXX_FLAGS_CCOV       "-O0 -std=c++11 -g --coverage")
 # Targets
 SET(TARGET_LIBNAME_COMMON "common-installer")
 SET(TARGET_LIBNAME_SIGNATURE "common-installer-signature")
+SET(TARGET_LIBNAME_UTILS "common-installer-utils")
 SET(TARGET_WGT_BACKEND "wgt-backend")
 SET(TARGET_XPK_BACKEND "xpk-backend")
 SET(TARGET_NATIVE_BACKEND "native-backend")
index 9eb8567..252889a 100644 (file)
@@ -67,6 +67,7 @@ ln -s %{_bindir}/xpk-backend %{buildroot}%{_sysconfdir}/package-manager/backend/
 %defattr(-,root,root)
 %{_libdir}/libcommon-installer.so*
 %{_libdir}/libcommon-installer-signature.so*
+%{_libdir}/libcommon-installer-utils.so*
 %{_datarootdir}/app-installers/signature_schema.xsd
 %license LICENSE LICENSE-xwalk
 
index 655404f..45b7ad2 100644 (file)
@@ -1,5 +1,6 @@
 ADD_SUBDIRECTORY(common)
 ADD_SUBDIRECTORY(signature)
+ADD_SUBDIRECTORY(utils)
 ADD_SUBDIRECTORY(wgt)
 #ADD_SUBDIRECTORY(xpk)
 #ADD_SUBDIRECTORY(native)
diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt
new file mode 100644 (file)
index 0000000..02b3efa
--- /dev/null
@@ -0,0 +1,21 @@
+# Target - sources
+SET(SRCS
+  utf_converter.cc
+  values.cc
+)
+# Target - definition
+ADD_LIBRARY(${TARGET_LIBNAME_UTILS} SHARED ${SRCS})
+# Target - includes
+TARGET_INCLUDE_DIRECTORIES(${TARGET_LIBNAME_UTILS} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../")
+
+# Target - deps
+APPLY_PKG_CONFIG(${TARGET_LIBNAME_UTILS} PUBLIC
+  Boost
+)
+
+# Extra
+SET_TARGET_PROPERTIES(${TARGET_LIBNAME_UTILS} PROPERTIES VERSION ${VERSION})
+SET_TARGET_PROPERTIES(${TARGET_LIBNAME_UTILS} PROPERTIES SOVERSION ${VERSION_MAJOR})
+
+# Install
+INSTALL(TARGETS ${TARGET_LIBNAME_UTILS} DESTINATION ${LIB_INSTALL_DIR})
diff --git a/src/utils/utf_converter.cc b/src/utils/utf_converter.cc
new file mode 100644 (file)
index 0000000..f2ef84d
--- /dev/null
@@ -0,0 +1,124 @@
+// Copyright (c) 2013 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/utf_converter.h"
+
+#include <memory>
+
+namespace {
+
+bool IsAlignedToMachineWord(const void* pointer) {
+  uintptr_t kMachineWordAlignmentMask = sizeof(uintptr_t) - 1;
+  return !(reinterpret_cast<uintptr_t>(pointer) & kMachineWordAlignmentMask);
+}
+
+template<typename T> inline T* AlignToMachineWord(T* pointer) {
+  uintptr_t kMachineWordAlignmentMask = sizeof(uintptr_t) - 1;
+  return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(pointer) &
+                              ~kMachineWordAlignmentMask);
+}
+
+template<size_t size, typename CharacterType> struct NonASCIIMask;
+template<> struct NonASCIIMask<4, char> {
+    static inline uint32_t value() { return 0x80808080U; }
+};
+template<> struct NonASCIIMask<8, char> {
+    static inline uint64_t value() { return 0x8080808080808080ULL; }
+};
+
+}  // namespace
+
+namespace common_installer {
+namespace utils {
+namespace utf_converter {
+
+using EncSt = __gnu_cxx::encoding_state;
+using codecvt_type16 = std::codecvt<char16_t, char, EncSt>;
+using codecvt_type8 = std::codecvt<char, char16_t, EncSt>;
+
+bool IsStringUTF8(const std::string& str) {
+  // TODO(jizydorczyk):
+  // Implement it.
+  // We need icu library from chromium to make it possible
+  // to properly implement this function, so it needs to be
+  // converted for our needs first.
+  return true;
+}
+
+bool IsStringASCII(const std::string& str) {
+    const char* characters = str.c_str();
+    size_t length = str.length();
+    uintptr_t all_char_bits = 0;
+    const char* end = characters + length;
+
+    // Prologue: align the input.
+    while (!IsAlignedToMachineWord(characters) && characters != end) {
+      all_char_bits |= *characters;
+      ++characters;
+    }
+
+    // Compare the values of CPU word size.
+    const char* word_end = AlignToMachineWord(end);
+    const size_t loop_increment = sizeof(uintptr_t) / sizeof(char);
+    while (characters < word_end) {
+      all_char_bits |= *(reinterpret_cast<const uintptr_t*>(characters));
+      characters += loop_increment;
+    }
+
+    // Process the remaining bytes.
+    while (characters != end) {
+      all_char_bits |= *characters;
+      ++characters;
+    }
+
+    uintptr_t non_ascii_bit_mask =
+        NonASCIIMask<sizeof(uintptr_t), char>::value();
+    return !(all_char_bits & non_ascii_bit_mask);
+}
+
+std::string UTF16ToUTF8(const std::u16string& s) {
+  std::locale loc(std::locale::classic(), new codecvt_type16);
+  EncSt state(UTF16::iconvName(), UTF8::iconvName());
+  const codecvt_type16& cvt = std::use_facet<codecvt_type16>(loc);
+
+  const char16_t* enx;
+
+  std::string buffer(s.size()*3, '\0');
+  char* inx;
+
+  codecvt_type16::result r =
+    cvt.out(state, &s[0], &s[s.size()], enx,
+        &buffer[0], &buffer[buffer.size()], inx);
+
+  if (r != codecvt_type16::ok)
+    return "";
+
+  buffer.resize(buffer.find("\0", 0, 1));
+  return buffer;
+}
+
+std::u16string UTF8ToUTF16(const std::string& s) {
+  std::locale loc(std::locale::classic(), new codecvt_type8);
+  EncSt state(UTF8::iconvName(), UTF16::iconvName());
+  const codecvt_type8& cvt = std::use_facet<codecvt_type8>(loc);
+
+  const char* enx;
+
+  std::u16string buffer(s.size()*2, '\0');
+  char16_t* inx;
+  codecvt_type8::result r =
+    cvt.out(state, &s[0], &s[s.size()], enx,
+        &buffer[0], &buffer[buffer.size()], inx);
+
+  if (r != codecvt_type8::ok)
+    return std::u16string();
+
+  buffer.resize(buffer.find(u"\0", 0, 1));
+  return buffer;
+}
+
+}  // namespace UtfConverter
+}  // namespace utils
+}  // namespace common_installer
diff --git a/src/utils/utf_converter.h b/src/utils/utf_converter.h
new file mode 100644 (file)
index 0000000..81d5086
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright (c) 2013 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.
+
+#ifndef UTILS_UTF_CONVERTER_H_
+#define UTILS_UTF_CONVERTER_H_
+
+// This is an extension to use iconv for dealing with character encodings.
+// This header is needed for conversions between various character sets.
+#include <ext/codecvt_specializations.h>
+
+#include <string>
+
+// With this macro we can determine endianess
+#define IS_BIG_ENDIAN (*(uint16_t *)"\0\xff" < 0x100)
+
+namespace common_installer {
+namespace utils {
+
+struct UTF8 {
+  static const char* iconvName() { return "UTF-8"; }
+};
+
+struct UTF16 {
+  static const char* iconvName() {
+    return IS_BIG_ENDIAN ? "UTF-16BE" : "UTF-16LE";
+  }
+};
+
+namespace utf_converter {
+  bool IsStringUTF8(const std::string& str);
+  bool IsStringASCII(const std::string& str);
+
+  std::string UTF16ToUTF8(const std::u16string& str);
+  std::u16string UTF8ToUTF16(const std::string& str);
+}  // namespace UtfConverter
+
+}  // namespace utils
+}  // namespace common_installer
+
+#endif  // UTILS_UTF_CONVERTER_H_
diff --git a/src/utils/values.cc b/src/utils/values.cc
new file mode 100644 (file)
index 0000000..5a096db
--- /dev/null
@@ -0,0 +1,1128 @@
+// 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),
+                       &current_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
diff --git a/src/utils/values.h b/src/utils/values.h
new file mode 100644 (file)
index 0000000..47c503e
--- /dev/null
@@ -0,0 +1,501 @@
+// 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_