2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Krzysztof Dynowski (k.dynowski@samsumg.com)
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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
22 * @author Krzysztof Dynowski (k.dynowski@samsumg.com)
23 * @brief KVStore visitor with defaults values from json
26 #ifndef CONFIG_FROM_KVJSON_VISITOR_HPP
27 #define CONFIG_FROM_KVJSON_VISITOR_HPP
29 #include "config/from-kvstore-visitor.hpp"
30 #include "config/is-union.hpp"
31 #include <json/json.h>
35 class FromKVJsonVisitor {
37 FromKVJsonVisitor(KVStore& store, const std::string& json, const std::string& prefix)
42 mObject = json_tokener_parse(json.c_str());
43 if (mObject == nullptr) {
44 throw ConfigException("Json parsing error");
49 ~FromKVJsonVisitor() {
50 json_object_put(mObject);
53 FromKVJsonVisitor(const FromKVJsonVisitor& v) :
54 mObject(v.mObject ? json_object_get(v.mObject) : nullptr),
56 mKeyPrefix(v.mKeyPrefix),
60 FromKVJsonVisitor& operator=(const FromKVJsonVisitor&) = delete;
63 void visit(const std::string& name, T& value) {
64 getValue(name, value);
69 std::string mKeyPrefix;
73 // create visitor for field object (visitable object)
74 FromKVJsonVisitor(const FromKVJsonVisitor& v, const std::string& name, const bool isUnion) :
76 mKeyPrefix(key(v.mKeyPrefix, name)),
77 mIsUnion(isUnion || v.mIsUnion)
79 json_object* object = nullptr;
80 if (v.mObject && !json_object_object_get_ex(v.mObject, name.c_str(), &object)) {
82 throw ConfigException("Missing json field " + mKeyPrefix);
84 mObject = object ? json_object_get(object) : nullptr;
87 // create visitor for vector i-th element (visitable object)
88 FromKVJsonVisitor(const FromKVJsonVisitor& v, int i, const bool isUnion) :
90 mKeyPrefix(key(v.mKeyPrefix, std::to_string(i))),
91 mIsUnion(isUnion || v.mIsUnion)
93 json_object* object = nullptr;
95 object = json_object_array_get_idx(v.mObject, i);
96 checkType(object, json_type_object);
98 mObject = object ? json_object_get(object) : nullptr;
101 template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
102 void getValue(const std::string& name, T& t)
104 std::string k = key(mKeyPrefix, name);
105 if (mStore.exists(k)) {
106 t = mStore.get<T>(k);
109 json_object* object = nullptr;
111 json_object_object_get_ex(mObject, name.c_str(), &object);
114 throw ConfigException("Missing json field " + key(mKeyPrefix, name));
116 fromJsonObject(object, t);
120 template<typename T, typename std::enable_if<isUnion<T>::value, int>::type = 0>
121 void getValue(const std::string& name, T& t)
123 FromKVJsonVisitor visitor(*this, name, true);
127 template<typename T, typename std::enable_if<isVisitable<T>::value && !isUnion<T>::value, int>::type = 0>
128 void getValue(const std::string& name, T& t)
130 FromKVJsonVisitor visitor(*this, name, false);
134 int getArraySize(std::string& name, json_object* object)
136 if (mStore.exists(name)) {
137 return mStore.get<int>(name);
140 return json_object_array_length(object);
146 void getValue(const std::string& name, std::vector<T>& value)
148 json_object* object = nullptr;
149 if (mObject && json_object_object_get_ex(mObject, name.c_str(), &object)) {
150 checkType(object, json_type_array);
153 std::string k = key(mKeyPrefix, name);
154 int length = getArraySize(k, object);
156 throw ConfigException("Missing array length " + k);
158 value.resize(static_cast<size_t>(length));
159 FromKVJsonVisitor visitor(*this, name, false);
160 if (mStore.exists(k)) {
161 json_object_put(visitor.mObject);
162 visitor.mObject = nullptr;
164 for (int i = 0; i < length; ++i) {
165 visitor.getValue(i, value[i]);
169 template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
170 void getValue(int i, T& t)
172 std::string k = key(mKeyPrefix, std::to_string(i));
173 if (mStore.exists(k)) {
174 t = mStore.get<T>(k);
177 json_object* object = mObject ? json_object_array_get_idx(mObject, i) : nullptr;
179 throw ConfigException("Missing json array elem " + k);
181 fromJsonObject(object, t);
185 template<typename T, typename std::enable_if<isUnion<T>::value, int>::type = 0>
186 void getValue(int i, T& t)
188 FromKVJsonVisitor visitor(*this, i, true);
192 template<typename T, typename std::enable_if<isVisitable<T>::value && !isUnion<T>::value, int>::type = 0>
193 void getValue(int i, T& t)
195 FromKVJsonVisitor visitor(*this, i, false);
200 void getValue(int i, std::vector<T>& value)
202 std::string k = key(mKeyPrefix, std::to_string(i));
203 int length = getArraySize(k, mObject);
204 value.resize(static_cast<size_t>(length));
205 FromKVJsonVisitor visitor(*this, i, false);
206 if (mStore.exists(k)) {
207 json_object_put(visitor.mObject);
208 visitor.mObject = nullptr;
210 for (int i = 0; i < length; ++i) {
211 visitor.getValue(i, value[i]);
215 static void checkType(json_object* object, json_type type)
217 if (type != json_object_get_type(object)) {
218 throw ConfigException("Invalid field type " + std::to_string(type));
222 static void fromJsonObject(json_object* object, int& value)
224 checkType(object, json_type_int);
225 std::int64_t value64 = json_object_get_int64(object);
226 if (value64 > INT32_MAX || value64 < INT32_MIN) {
227 throw ConfigException("Value out of range");
229 value = static_cast<int>(value64);
232 static void fromJsonObject(json_object* object, std::int64_t& value)
234 checkType(object, json_type_int);
235 value = json_object_get_int64(object);
238 static void fromJsonObject(json_object* object, bool& value)
240 checkType(object, json_type_boolean);
241 value = json_object_get_boolean(object);
244 static void fromJsonObject(json_object* object, double& value)
246 checkType(object, json_type_double);
247 value = json_object_get_double(object);
250 static void fromJsonObject(json_object* object, std::string& value)
252 checkType(object, json_type_string);
253 value = json_object_get_string(object);
257 } // namespace config
259 #endif // CONFIG_FROM_KVJSON_VISITOR_HPP