text: // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #ifndef TOOLS_JSON_SCHEMA_COMPILER_UTIL_H__
  #define TOOLS_JSON_SCHEMA_COMPILER_UTIL_H__
  
  #include <string>
  #include <vector>
  
  #include "base/memory/linked_ptr.h"
  #include "base/memory/scoped_ptr.h"
  #include "base/values.h"
  
  namespace json_schema_compiler {
  
  namespace util {
  
  // Creates a new item at |out| from |from|[|index|]. These are used by template
  // specializations of |Get(Optional)ArrayFromList|.
  bool GetItemFromList(const base::ListValue& from, int index, int* out);
  bool GetItemFromList(const base::ListValue& from, int index, bool* out);
  bool GetItemFromList(const base::ListValue& from, int index, double* out);
  bool GetItemFromList(const base::ListValue& from, int index, std::string* out);
  bool GetItemFromList(const base::ListValue& from,
                       int index,
                       linked_ptr<base::Value>* out);
  bool GetItemFromList(const base::ListValue& from,
                       int index,
                       linked_ptr<base::DictionaryValue>* out);
  
  // This template is used for types generated by tools/json_schema_compiler.
  template<class T>
  bool GetItemFromList(const base::ListValue& from,
                       int index,
                       linked_ptr<T>* out) {
    const base::DictionaryValue* dict;
    if (!from.GetDictionary(index, &dict))
      return false;
    scoped_ptr<T> obj(new T());
    if (!T::Populate(*dict, obj.get()))
      return false;
    *out = linked_ptr<T>(obj.release());
    return true;
  }
  
  // Populates |out| with |list|. Returns false if there is no list at the
  // specified key or if the list has anything other than |T|.
  template <class T>
  bool PopulateArrayFromList(
      const base::ListValue& list, std::vector<T>* out) {
    out->clear();
    T value;
    for (size_t i = 0; i < list.GetSize(); ++i) {
      if (!GetItemFromList(list, i, &value))
        return false;
      out->push_back(value);
    }
  
    return true;
  }
  
  // Populates |out| with |from|.|name|. Returns false if there is no list at
  // the specified key or if the list has anything other than |T|.
  template <class T>
  bool PopulateArrayFromDictionary(
      const base::DictionaryValue& from,
      const std::string& name,
      std::vector<T>* out) {
    const base::ListValue* list = NULL;
    if (!from.GetListWithoutPathExpansion(name, &list))
      return false;
  
    return PopulateArrayFromList(*list, out);
  }
  
  // Creates a new vector containing |list| at |out|. Returns
  // true on success or if there is nothing at the specified key. Returns false
  // if anything other than a list of |T| is at the specified key.
  template <class T>
  bool PopulateOptionalArrayFromList(
      const base::ListValue& list,
      scoped_ptr<std::vector<T> >* out) {
    out->reset(new std::vector<T>());
    T value;
    for (size_t i = 0; i < list.GetSize(); ++i) {
      if (!GetItemFromList(list, i, &value)) {
        out->reset();
        return false;
      }
      (*out)->push_back(value);
    }
  
    return true;
  }
  
  // Creates a new vector containing |from|.|name| at |out|. Returns
  // true on success or if there is nothing at the specified key. Returns false
  // if anything other than a list of |T| is at the specified key.
  template <class T>
  bool PopulateOptionalArrayFromDictionary(
      const base::DictionaryValue& from,
      const std::string& name,
      scoped_ptr<std::vector<T> >* out) {
    const base::ListValue* list = NULL;
    {
      const base::Value* maybe_list = NULL;
      // Since |name| is optional, its absence is acceptable. However, anything
      // other than a ListValue is not.
      if (!from.GetWithoutPathExpansion(name, &maybe_list))
        return true;
      if (!maybe_list->IsType(base::Value::TYPE_LIST))
        return false;
      list = static_cast<const base::ListValue*>(maybe_list);
    }
  
    return PopulateOptionalArrayFromList(*list, out);
  }
  
  // Appends a Value newly created from |from| to |out|. These used by template
  // specializations of |Set(Optional)ArrayToList|.
  void AddItemToList(const int from, base::ListValue* out);
  void AddItemToList(const bool from, base::ListValue* out);
  void AddItemToList(const double from, base::ListValue* out);
  void AddItemToList(const std::string& from, base::ListValue* out);
  void AddItemToList(const linked_ptr<base::Value>& from,
                     base::ListValue* out);
  void AddItemToList(const linked_ptr<base::DictionaryValue>& from,
                     base::ListValue* out);
  
  // This template is used for types generated by tools/json_schema_compiler.
  template<class T>
  void AddItemToList(const linked_ptr<T>& from, base::ListValue* out) {
    out->Append(from->ToValue().release());
  }
  
  // Set |out| to the the contents of |from|. Requires GetItemFromList to be
  // implemented for |T|.
  template <class T>
  void PopulateListFromArray(
      const std::vector<T>& from,
      base::ListValue* out) {
    out->Clear();
    for (typename std::vector<T>::const_iterator it = from.begin();
        it != from.end(); ++it) {
      AddItemToList(*it, out);
    }
  }
  
  // Set |out| to the the contents of |from| if |from| is non-NULL. Requires
  // GetItemFromList to be implemented for |T|.
  template <class T>
  void PopulateListFromOptionalArray(
      const scoped_ptr<std::vector<T> >& from,
      base::ListValue* out) {
    if (from.get())
      PopulateListFromArray(*from, out);
  
  }
  
  template <class T>
  scoped_ptr<base::Value> CreateValueFromArray(const std::vector<T>& from) {
    base::ListValue* list = new base::ListValue();
    PopulateListFromArray(from, list);
    return scoped_ptr<base::Value>(list);
  }
  
  template <class T>
  scoped_ptr<base::Value> CreateValueFromOptionalArray(
      const scoped_ptr<std::vector<T> >& from) {
    if (from.get())
      return CreateValueFromArray(*from);
    return scoped_ptr<base::Value>();
  }
  
  std::string ValueTypeToString(Value::Type type);
  
  }  // namespace util
  }  // namespace json_schema_compiler
  
  #endif // TOOLS_JSON_SCHEMA_COMPILER_UTIL_H__
  