Fork Vasum on GitHub Official Vasum Wiki on Tizen.org
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
from-json-visitor.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Contact: Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License
17  */
18 
25 #ifndef CARGO_JSON_FROM_JSON_VISITOR_HPP
26 #define CARGO_JSON_FROM_JSON_VISITOR_HPP
27 
28 #include "cargo/is-visitable.hpp"
29 #include "cargo/is-like-tuple.hpp"
30 #include "cargo/exception.hpp"
31 #include "cargo/visit-fields.hpp"
32 
33 #include <json.h>
34 #include <string>
35 #include <cstring>
36 #include <vector>
37 #include <array>
38 #include <utility>
39 #include <limits>
40 
41 namespace cargo {
42 
44 public:
45  explicit FromJsonVisitor(const std::string& jsonString)
46  : mObject(nullptr)
47  {
48  mObject = json_tokener_parse(jsonString.c_str());
49  if (mObject == nullptr) {
50  throw CargoException("Json parsing error");
51  }
52  }
53 
55  : mObject(json_object_get(visitor.mObject))
56  {
57  }
58 
60  {
61  json_object_put(mObject);
62  }
63 
64  FromJsonVisitor& operator=(const FromJsonVisitor&) = delete;
65 
66  template<typename T>
67  void visit(const std::string& name, T& value)
68  {
69  json_object* object = nullptr;
70  if (!json_object_object_get_ex(mObject, name.c_str(), &object)) {
71  throw CargoException("Missing field '" + name + "'");
72  }
73  fromJsonObject(object, value);
74  }
75 
76 private:
77  json_object* mObject;
78 
79 
80  explicit FromJsonVisitor(json_object* object)
81  : mObject(json_object_get(object))
82  {
83  }
84 
85  static void checkType(json_object* object, json_type type)
86  {
87  if (type != json_object_get_type(object)) {
88  throw CargoException("Invalid field type");
89  }
90  }
91 
92  template<typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
93  static void fromJsonObject(json_object* object, T& value)
94  {
95  checkType(object, json_type_int);
96  typedef typename std::conditional<std::is_signed<T>::value,
97  std::int64_t, std::uint64_t>::type BufferType;
98  BufferType value64 = json_object_get_int64(object);
99  if (value64 > std::numeric_limits<T>::max() || value64 < std::numeric_limits<T>::min()) {
100  throw CargoException("Value out of range");
101  }
102  value = static_cast<T>(value64);
103  }
104 
105  static void fromJsonObject(json_object* object, bool& value)
106  {
107  checkType(object, json_type_boolean);
108  value = json_object_get_boolean(object);
109  }
110 
111  static void fromJsonObject(json_object* object, double& value)
112  {
113  checkType(object, json_type_double);
114  value = json_object_get_double(object);
115  }
116 
117  static void fromJsonObject(json_object* object, std::string& value)
118  {
119  checkType(object, json_type_string);
120  value = json_object_get_string(object);
121  }
122 
123  static void fromJsonObject(json_object* object, char* &value)
124  {
125  checkType(object, json_type_string);
126 
127  int len = json_object_get_string_len(object);
128  value = new char[len + 1];
129  std::strncpy(value, json_object_get_string(object), len);
130  value[len] = '\0';
131  }
132 
133  template<typename T>
134  static void fromJsonObject(json_object* object, std::vector<T>& values)
135  {
136  checkType(object, json_type_array);
137  int length = json_object_array_length(object);
138  values.resize(static_cast<size_t>(length));
139  for (int i = 0; i < length; ++i) {
140  fromJsonObject(json_object_array_get_idx(object, i), values[static_cast<size_t>(i)]);
141  }
142  }
143 
144  template<typename T, std::size_t N>
145  static void fromJsonObject(json_object* object, std::array<T, N>& values)
146  {
147  checkType(object, json_type_array);
148 
149  for (std::size_t i = 0; i < N; ++i) {
150  fromJsonObject(json_object_array_get_idx(object, i), values[i]);
151  }
152  }
153 
154  template<typename V>
155  static void fromJsonObject(json_object* object, std::map<std::string, V>& values)
156  {
157  checkType(object, json_type_object);
158 
159  json_object_object_foreach(object, key, val) {
160  fromJsonObject(val, values[key]);
161  }
162  }
163 
165  {
166  template<typename T>
167  static void visit(json_object* object, std::size_t& idx, T&& value)
168  {
169  fromJsonObject(json_object_array_get_idx(object, idx), value);
170  idx += 1;
171  }
172  };
173 
174  template<typename T, typename std::enable_if<isLikeTuple<T>::value, int>::type = 0>
175  static void fromJsonObject(json_object* object, T& values)
176  {
177  checkType(object, json_type_array);
178 
179  std::size_t idx = 0;
180  HelperVisitor visitor;
181  visitFields(values, &visitor, object, idx);
182  }
183 
184  template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
185  static void fromJsonObject(json_object* object, T& value)
186  {
187  fromJsonObject(object,
188  *reinterpret_cast<typename std::underlying_type<T>::type*>(&value));
189  }
190 
191  template<typename T, typename std::enable_if<isVisitable<T>::value, int>::type = 0>
192  static void fromJsonObject(json_object* object, T& value)
193  {
194  checkType(object, json_type_object);
195  FromJsonVisitor visitor(object);
196  value.accept(visitor);
197  }
198 };
199 
200 } // namespace cargo
201 
202 #endif // CARGO_JSON_FROM_JSON_VISITOR_HPP
Definition: from-json-visitor.hpp:43
Internal configuration helper.
static void fromJsonObject(json_object *object, std::string &value)
Definition: from-json-visitor.hpp:117
static void checkType(json_object *object, json_type type)
Definition: from-json-visitor.hpp:85
FromJsonVisitor(const FromJsonVisitor &visitor)
Definition: from-json-visitor.hpp:54
FromJsonVisitor(json_object *object)
Definition: from-json-visitor.hpp:80
static void fromJsonObject(json_object *object, char *&value)
Definition: from-json-visitor.hpp:123
Helper function for iterating tuples, pairs and arrays.
json_object * mObject
Definition: from-json-visitor.hpp:77
~FromJsonVisitor()
Definition: from-json-visitor.hpp:59
static void fromJsonObject(json_object *object, bool &value)
Definition: from-json-visitor.hpp:105
static void fromJsonObject(json_object *object, std::array< T, N > &values)
Definition: from-json-visitor.hpp:145
Tuple or pair checker.
static void fromJsonObject(json_object *object, T &value)
Definition: from-json-visitor.hpp:93
std::string key(const Arg1 &a1, const Args &...args)
Concatenates all parameters into one std::string.
Definition: kvstore-visitor-utils.hpp:60
FromJsonVisitor & operator=(const FromJsonVisitor &)=delete
Exceptions for libcargo.
Definition: from-json-visitor.hpp:164
static void fromJsonObject(json_object *object, std::map< std::string, V > &values)
Definition: from-json-visitor.hpp:155
void visit(const std::string &name, T &value)
Definition: from-json-visitor.hpp:67
Base class for exceptions in libcargo.
Definition: exception.hpp:35
static void visit(json_object *object, std::size_t &idx, T &&value)
Definition: from-json-visitor.hpp:167
static void fromJsonObject(json_object *object, std::vector< T > &values)
Definition: from-json-visitor.hpp:134
FromJsonVisitor(const std::string &jsonString)
Definition: from-json-visitor.hpp:45
static void fromJsonObject(json_object *object, double &value)
Definition: from-json-visitor.hpp:111
static void fromJsonObject(json_object *object, T &values)
Definition: from-json-visitor.hpp:175
void visitFields(T &t, F f, A...args)
Definition: visit-fields.hpp:58