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(const std::string& db, const std::string& json, const std::string& prefix)
38 : mStorePtr(new KVStore(db))
41 , mTransaction(mStorePtr->getTransaction())
43 mObject = json_tokener_parse(json.c_str());
44 if (mObject == nullptr) {
45 throw ConfigException("Json parsing error");
50 ~FromKVJsonVisitor() {
51 json_object_put(mObject);
54 FromKVJsonVisitor(const FromKVJsonVisitor& v) :
55 mObject(v.mObject ? json_object_get(v.mObject) : nullptr),
56 mStorePtr(v.mStorePtr),
57 mKeyPrefix(v.mKeyPrefix),
59 mTransaction(v.mTransaction)
62 FromKVJsonVisitor& operator=(const FromKVJsonVisitor&) = delete;
65 void visit(const std::string& name, T& value) {
66 getValue(name, value);
70 std::shared_ptr<KVStore> mStorePtr;
71 std::string mKeyPrefix;
74 KVStore::Transaction mTransaction;
76 // create visitor for field object (visitable object)
77 FromKVJsonVisitor(const FromKVJsonVisitor& v, const std::string& name, const bool isUnion) :
78 mStorePtr(v.mStorePtr),
79 mKeyPrefix(key(v.mKeyPrefix, name)),
80 mIsUnion(isUnion || v.mIsUnion),
81 mTransaction(v.mTransaction)
83 json_object* object = nullptr;
84 if (v.mObject && !json_object_object_get_ex(v.mObject, name.c_str(), &object)) {
86 throw ConfigException("Missing json field " + mKeyPrefix);
88 mObject = object ? json_object_get(object) : nullptr;
91 // create visitor for vector i-th element (visitable object)
92 FromKVJsonVisitor(const FromKVJsonVisitor& v, int i, const bool isUnion) :
93 mStorePtr(v.mStorePtr),
94 mKeyPrefix(key(v.mKeyPrefix, std::to_string(i))),
95 mIsUnion(isUnion || v.mIsUnion),
96 mTransaction(v.mTransaction)
98 json_object* object = nullptr;
100 object = json_object_array_get_idx(v.mObject, i);
101 checkType(object, json_type_object);
103 mObject = object ? json_object_get(object) : nullptr;
106 template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
107 void getValue(const std::string& name, T& t)
109 std::string k = key(mKeyPrefix, name);
110 if (mStorePtr->exists(k)) {
111 t = mStorePtr->get<T>(k);
114 json_object* object = nullptr;
116 json_object_object_get_ex(mObject, name.c_str(), &object);
119 throw ConfigException("Missing json field " + key(mKeyPrefix, name));
121 fromJsonObject(object, t);
125 template<typename T, typename std::enable_if<isUnion<T>::value, int>::type = 0>
126 void getValue(const std::string& name, T& t)
128 FromKVJsonVisitor visitor(*this, name, true);
132 template<typename T, typename std::enable_if<isVisitable<T>::value && !isUnion<T>::value, int>::type = 0>
133 void getValue(const std::string& name, T& t)
135 FromKVJsonVisitor visitor(*this, name, false);
139 int getArraySize(std::string& name, json_object* object)
141 if (mStorePtr->exists(name)) {
142 return mStorePtr->get<int>(name);
145 return json_object_array_length(object);
151 void getValue(const std::string& name, std::vector<T>& value)
153 json_object* object = nullptr;
154 if (mObject && json_object_object_get_ex(mObject, name.c_str(), &object)) {
155 checkType(object, json_type_array);
158 std::string k = key(mKeyPrefix, name);
159 int length = getArraySize(k, object);
161 throw ConfigException("Missing array length " + k);
163 value.resize(static_cast<size_t>(length));
164 FromKVJsonVisitor visitor(*this, name, false);
165 if (mStorePtr->exists(k)) {
166 json_object_put(visitor.mObject);
167 visitor.mObject = nullptr;
169 for (int i = 0; i < length; ++i) {
170 visitor.getValue(i, value[i]);
174 template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
175 void getValue(int i, T& t)
177 std::string k = key(mKeyPrefix, std::to_string(i));
178 if (mStorePtr->exists(k)) {
179 t = mStorePtr->get<T>(k);
182 json_object* object = mObject ? json_object_array_get_idx(mObject, i) : nullptr;
184 throw ConfigException("Missing json array elem " + k);
186 fromJsonObject(object, t);
190 template<typename T, typename std::enable_if<isUnion<T>::value, int>::type = 0>
191 void getValue(int i, T& t)
193 FromKVJsonVisitor visitor(*this, i, true);
197 template<typename T, typename std::enable_if<isVisitable<T>::value && !isUnion<T>::value, int>::type = 0>
198 void getValue(int i, T& t)
200 FromKVJsonVisitor visitor(*this, i, false);
205 void getValue(int i, std::vector<T>& value)
207 std::string k = key(mKeyPrefix, std::to_string(i));
208 int length = getArraySize(k, mObject);
209 value.resize(static_cast<size_t>(length));
210 FromKVJsonVisitor visitor(*this, i, false);
211 if (mStorePtr->exists(k)) {
212 json_object_put(visitor.mObject);
213 visitor.mObject = nullptr;
215 for (int i = 0; i < length; ++i) {
216 visitor.getValue(i, value[i]);
220 static void checkType(json_object* object, json_type type)
222 if (type != json_object_get_type(object)) {
223 throw ConfigException("Invalid field type " + std::to_string(type));
227 static void fromJsonObject(json_object* object, int& value)
229 checkType(object, json_type_int);
230 std::int64_t value64 = json_object_get_int64(object);
231 if (value64 > INT32_MAX || value64 < INT32_MIN) {
232 throw ConfigException("Value out of range");
234 value = static_cast<int>(value64);
237 static void fromJsonObject(json_object* object, std::int64_t& value)
239 checkType(object, json_type_int);
240 value = json_object_get_int64(object);
243 static void fromJsonObject(json_object* object, bool& value)
245 checkType(object, json_type_boolean);
246 value = json_object_get_boolean(object);
249 static void fromJsonObject(json_object* object, double& value)
251 checkType(object, json_type_double);
252 value = json_object_get_double(object);
255 static void fromJsonObject(json_object* object, std::string& value)
257 checkType(object, json_type_string);
258 value = json_object_get_string(object);
262 } // namespace config
264 #endif // CONFIG_FROM_KVJSON_VISITOR_HPP