1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef TOOLS_JSON_SCHEMA_COMPILER_UTIL_H__
6#define TOOLS_JSON_SCHEMA_COMPILER_UTIL_H__
7
8#include <string>
9#include <vector>
10
11#include "base/memory/linked_ptr.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/values.h"
14
15namespace json_schema_compiler {
16
17namespace util {
18
19// Creates a new item at |out| from |from|[|index|]. These are used by template
20// specializations of |Get(Optional)ArrayFromList|.
21bool GetItemFromList(const base::ListValue& from, int index, int* out);
22bool GetItemFromList(const base::ListValue& from, int index, bool* out);
23bool GetItemFromList(const base::ListValue& from, int index, double* out);
24bool GetItemFromList(const base::ListValue& from, int index, std::string* out);
25bool GetItemFromList(const base::ListValue& from,
26                     int index,
27                     linked_ptr<base::Value>* out);
28bool GetItemFromList(const base::ListValue& from,
29                     int index,
30                     linked_ptr<base::DictionaryValue>* out);
31
32// This template is used for types generated by tools/json_schema_compiler.
33template<class T>
34bool GetItemFromList(const base::ListValue& from,
35                     int index,
36                     linked_ptr<T>* out) {
37  const base::DictionaryValue* dict;
38  if (!from.GetDictionary(index, &dict))
39    return false;
40  scoped_ptr<T> obj(new T());
41  if (!T::Populate(*dict, obj.get()))
42    return false;
43  *out = linked_ptr<T>(obj.release());
44  return true;
45}
46
47// Populates |out| with |list|. Returns false if there is no list at the
48// specified key or if the list has anything other than |T|.
49template <class T>
50bool PopulateArrayFromList(
51    const base::ListValue& list, std::vector<T>* out) {
52  out->clear();
53  T value;
54  for (size_t i = 0; i < list.GetSize(); ++i) {
55    if (!GetItemFromList(list, i, &value))
56      return false;
57    out->push_back(value);
58  }
59
60  return true;
61}
62
63// Populates |out| with |from|.|name|. Returns false if there is no list at
64// the specified key or if the list has anything other than |T|.
65template <class T>
66bool PopulateArrayFromDictionary(
67    const base::DictionaryValue& from,
68    const std::string& name,
69    std::vector<T>* out) {
70  const base::ListValue* list = NULL;
71  if (!from.GetListWithoutPathExpansion(name, &list))
72    return false;
73
74  return PopulateArrayFromList(*list, out);
75}
76
77// Creates a new vector containing |list| at |out|. Returns
78// true on success or if there is nothing at the specified key. Returns false
79// if anything other than a list of |T| is at the specified key.
80template <class T>
81bool PopulateOptionalArrayFromList(
82    const base::ListValue& list,
83    scoped_ptr<std::vector<T> >* out) {
84  out->reset(new std::vector<T>());
85  T value;
86  for (size_t i = 0; i < list.GetSize(); ++i) {
87    if (!GetItemFromList(list, i, &value)) {
88      out->reset();
89      return false;
90    }
91    (*out)->push_back(value);
92  }
93
94  return true;
95}
96
97// Creates a new vector containing |from|.|name| at |out|. Returns
98// true on success or if there is nothing at the specified key. Returns false
99// if anything other than a list of |T| is at the specified key.
100template <class T>
101bool PopulateOptionalArrayFromDictionary(
102    const base::DictionaryValue& from,
103    const std::string& name,
104    scoped_ptr<std::vector<T> >* out) {
105  const base::ListValue* list = NULL;
106  {
107    const base::Value* maybe_list = NULL;
108    // Since |name| is optional, its absence is acceptable. However, anything
109    // other than a ListValue is not.
110    if (!from.GetWithoutPathExpansion(name, &maybe_list))
111      return true;
112    if (!maybe_list->IsType(base::Value::TYPE_LIST))
113      return false;
114    list = static_cast<const base::ListValue*>(maybe_list);
115  }
116
117  return PopulateOptionalArrayFromList(*list, out);
118}
119
120// Appends a Value newly created from |from| to |out|. These used by template
121// specializations of |Set(Optional)ArrayToList|.
122void AddItemToList(const int from, base::ListValue* out);
123void AddItemToList(const bool from, base::ListValue* out);
124void AddItemToList(const double from, base::ListValue* out);
125void AddItemToList(const std::string& from, base::ListValue* out);
126void AddItemToList(const linked_ptr<base::Value>& from,
127                   base::ListValue* out);
128void AddItemToList(const linked_ptr<base::DictionaryValue>& from,
129                   base::ListValue* out);
130
131// This template is used for types generated by tools/json_schema_compiler.
132template<class T>
133void AddItemToList(const linked_ptr<T>& from, base::ListValue* out) {
134  out->Append(from->ToValue().release());
135}
136
137// Set |out| to the the contents of |from|. Requires GetItemFromList to be
138// implemented for |T|.
139template <class T>
140void PopulateListFromArray(
141    const std::vector<T>& from,
142    base::ListValue* out) {
143  out->Clear();
144  for (typename std::vector<T>::const_iterator it = from.begin();
145      it != from.end(); ++it) {
146    AddItemToList(*it, out);
147  }
148}
149
150// Set |out| to the the contents of |from| if |from| is non-NULL. Requires
151// GetItemFromList to be implemented for |T|.
152template <class T>
153void PopulateListFromOptionalArray(
154    const scoped_ptr<std::vector<T> >& from,
155    base::ListValue* out) {
156  if (from.get())
157    PopulateListFromArray(*from, out);
158
159}
160
161template <class T>
162scoped_ptr<base::Value> CreateValueFromArray(const std::vector<T>& from) {
163  base::ListValue* list = new base::ListValue();
164  PopulateListFromArray(from, list);
165  return scoped_ptr<base::Value>(list);
166}
167
168template <class T>
169scoped_ptr<base::Value> CreateValueFromOptionalArray(
170    const scoped_ptr<std::vector<T> >& from) {
171  if (from.get())
172    return CreateValueFromArray(*from);
173  return scoped_ptr<base::Value>();
174}
175
176std::string ValueTypeToString(base::Value::Type type);
177
178}  // namespace util
179}  // namespace json_schema_compiler
180
181#endif // TOOLS_JSON_SCHEMA_COMPILER_UTIL_H__
182