Fix arrays in kvjson visitor, prohibit empty db name
[archive/platform/core/system/libConfig.git] / src / config / from-kvjson-visitor.hpp
1 #ifndef CONFIG_FROM_KVJSON_VISITOR_HPP
2 #define CONFIG_FROM_KVJSON_VISITOR_HPP
3
4 /*
5  *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
6  *
7  *  Contact: Krzysztof Dynowski (k.dynowski@samsumg.com)
8  *
9  *  Licensed under the Apache License, Version 2.0 (the "License");
10  *  you may not use this file except in compliance with the License.
11  *  You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  *  Unless required by applicable law or agreed to in writing, software
16  *  distributed under the License is distributed on an "AS IS" BASIS,
17  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  *  See the License for the specific language governing permissions and
19  *  limitations under the License
20  */
21
22
23 /**
24  * @file
25  * @author  Krzysztof Dynowski (k.dynowski@samsumg.com)
26  * @brief   KVStore visitor with defaults values from json
27  */
28
29 #include "config/manager.hpp"
30
31
32 namespace config {
33
34 class FromKVJsonVisitor {
35 public:
36     FromKVJsonVisitor(const std::string& db, const std::string& json) :
37         mStorePtr(new KVStore(db))
38     {
39         mObject = json_tokener_parse(json.c_str());
40         if (mObject == nullptr) {
41             throw ConfigException("Json parsing error");
42         }
43     }
44
45     ~FromKVJsonVisitor() {
46         json_object_put(mObject);
47     }
48
49     FromKVJsonVisitor(const FromKVJsonVisitor& v) :
50         mObject(json_object_get(v.mObject)),
51         mStorePtr(v.mStorePtr),
52         mKeyPrefix(v.mKeyPrefix)
53     {
54     }
55     FromKVJsonVisitor& operator=(const FromKVJsonVisitor&) = delete;
56
57     template<typename T>
58     void visit(const std::string& name, T& value) {
59         getValue(name, value);
60     }
61
62 private:
63     std::shared_ptr<KVStore> mStorePtr;
64     std::string mKeyPrefix;
65     json_object* mObject;
66
67     // create visitor for field object (visitable object)
68     FromKVJsonVisitor(const FromKVJsonVisitor& v, const std::string& name) :
69         mStorePtr(v.mStorePtr)
70     {
71         json_object* object;
72         if (!json_object_object_get_ex(v.mObject, name.c_str(), &object)) {
73             throw ConfigException("Missing json field " + key(mKeyPrefix, name));
74         }
75         mObject = json_object_get(object);
76         mKeyPrefix = key(v.mKeyPrefix, name);
77     }
78
79     // create visitor for vector i-th element (visitable object)
80     FromKVJsonVisitor(const FromKVJsonVisitor& v, int i) :
81         mStorePtr(v.mStorePtr)
82     {
83         json_object* object = json_object_array_get_idx(v.mObject, i);
84         checkType(object, json_type_object);
85         mObject = json_object_get(object);
86         mKeyPrefix = key(v.mKeyPrefix, std::to_string(i));
87     }
88
89     template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
90     void getValue(const std::string& name, T& t)
91     {
92         json_object* object;
93         if (!json_object_object_get_ex(mObject, name.c_str(), &object)) {
94             throw ConfigException("Missing json field " + key(mKeyPrefix, name));
95         }
96         std::string k = key(mKeyPrefix, name);
97         if (mStorePtr->exists(k)) {
98             t = mStorePtr->get<T>(k);
99         }
100         else {
101             fromJsonObject(object, t);
102         }
103     }
104
105     template<typename T, typename std::enable_if<isVisitable<T>::value, int>::type = 0>
106     void getValue(const std::string& name, T& t)
107     {
108         FromKVJsonVisitor visitor(*this, name);
109         t.accept(visitor);
110     }
111
112     int getArraySize(std::string& name, json_object* object)
113     {
114         if (mStorePtr->exists(name)) {
115             return mStorePtr->get<int>(name);
116         }
117         return json_object_array_length(object);
118     }
119
120     template<typename T>
121     void getValue(const std::string& name, std::vector<T>& value)
122     {
123         json_object* object;
124         if (!json_object_object_get_ex(mObject, name.c_str(), &object)) {
125             throw ConfigException("Missing json field " + key(mKeyPrefix, name));
126         }
127         checkType(object, json_type_array);
128
129         std::string k = key(mKeyPrefix, name);
130         int length = getArraySize(k, object);
131         value.resize(static_cast<size_t>(length));
132         FromKVJsonVisitor visitor(*this, name);
133         for (int i = 0; i < length; ++i) {
134             visitor.getValue(i, value[i]);
135         }
136     }
137
138     template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
139     void getValue(int i, T& t)
140     {
141         json_object* object = json_object_array_get_idx(mObject, i);
142         std::string k = key(mKeyPrefix, std::to_string(i));
143         if (mStorePtr->exists(k)) {
144             t = mStorePtr->get<T>(k);
145         }
146         else {
147             fromJsonObject(object, t);
148         }
149     }
150
151     template<typename T, typename std::enable_if<isVisitable<T>::value, int>::type = 0>
152     void getValue(int i, T& t)
153     {
154         FromKVJsonVisitor visitor(*this, i);
155         t.accept(visitor);
156     }
157
158     template<typename T>
159     void getValue(int i, std::vector<T>& value)
160     {
161         std::string k = key(mKeyPrefix, std::to_string(i));
162         int length = getArraySize(k, mObject);
163         value.resize(static_cast<size_t>(length));
164         FromKVJsonVisitor visitor(*this, i);
165         for (int i = 0; i < length; ++i) {
166             visitor.getValue(i, value[i]);
167         }
168     }
169
170     static void checkType(json_object* object, json_type type)
171     {
172         if (type != json_object_get_type(object)) {
173             throw ConfigException("Invalid field type " + std::to_string(type));
174         }
175     }
176
177     static void fromJsonObject(json_object* object, int& value)
178     {
179         checkType(object, json_type_int);
180         std::int64_t value64 = json_object_get_int64(object);
181         if (value64 > INT32_MAX || value64 < INT32_MIN) {
182             throw ConfigException("Value out of range");
183         }
184         value = static_cast<int>(value64);
185     }
186
187     static void fromJsonObject(json_object* object, std::int64_t& value)
188     {
189         checkType(object, json_type_int);
190         value = json_object_get_int64(object);
191     }
192
193     static void fromJsonObject(json_object* object, bool& value)
194     {
195         checkType(object, json_type_boolean);
196         value = json_object_get_boolean(object);
197     }
198
199     static void fromJsonObject(json_object* object, double& value)
200     {
201         checkType(object, json_type_double);
202         value = json_object_get_double(object);
203     }
204
205     static void fromJsonObject(json_object* object, std::string& value)
206     {
207         checkType(object, json_type_string);
208         value = json_object_get_string(object);
209     }
210 };
211
212 } // namespace config
213
214 #endif // CONFIG_FROM_KVJSON_VISITOR_HPP