41b09cd87019372bcb27dd8247992ea4b2e36e4c
[archive/platform/core/system/libConfig.git] / src / config / from-json-visitor.hpp
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
19 /**
20  * @file
21  * @author  Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
22  * @brief   JSON visitor
23  */
24
25 #ifndef CONFIG_FROM_JSON_VISITOR_HPP
26 #define CONFIG_FROM_JSON_VISITOR_HPP
27
28 #include "config/is-visitable.hpp"
29 #include "config/exception.hpp"
30
31 #include <json/json.h>
32 #include <string>
33 #include <vector>
34
35 namespace config {
36
37 class FromJsonVisitor {
38 public:
39     explicit FromJsonVisitor(const std::string& jsonString)
40         : mObject(nullptr)
41     {
42         mObject = json_tokener_parse(jsonString.c_str());
43         if (mObject == nullptr) {
44             throw ConfigException("Json parsing error");
45         }
46     }
47
48     FromJsonVisitor(const FromJsonVisitor& visitor)
49         : mObject(json_object_get(visitor.mObject))
50     {
51     }
52
53     ~FromJsonVisitor()
54     {
55         json_object_put(mObject);
56     }
57
58     FromJsonVisitor& operator=(const FromJsonVisitor&) = delete;
59
60     template<typename T>
61     void visit(const std::string& name, T& value)
62     {
63         json_object* object = nullptr;
64         if (!json_object_object_get_ex(mObject, name.c_str(), &object)) {
65             throw ConfigException("Missing field '" + name + "'");
66         }
67         fromJsonObject(object, value);
68     }
69
70 private:
71     json_object* mObject;
72
73
74     explicit FromJsonVisitor(json_object* object)
75         : mObject(json_object_get(object))
76     {
77     }
78
79     static void checkType(json_object* object, json_type type)
80     {
81         if (type != json_object_get_type(object)) {
82             throw ConfigException("Invalid field type");
83         }
84     }
85
86     static void fromJsonObject(json_object* object, int& value)
87     {
88         checkType(object, json_type_int);
89         std::int64_t value64 = json_object_get_int64(object);
90         if (value64 > INT32_MAX || value64 < INT32_MIN) {
91             throw ConfigException("Value out of range");
92         }
93         value = static_cast<int>(value64);
94     }
95
96     static void fromJsonObject(json_object* object, std::int64_t& value)
97     {
98         checkType(object, json_type_int);
99         value = json_object_get_int64(object);
100     }
101
102     static void fromJsonObject(json_object* object, bool& value)
103     {
104         checkType(object, json_type_boolean);
105         value = json_object_get_boolean(object);
106     }
107
108     static void fromJsonObject(json_object* object, double& value)
109     {
110         checkType(object, json_type_double);
111         value = json_object_get_double(object);
112     }
113
114     static void fromJsonObject(json_object* object, std::string& value)
115     {
116         checkType(object, json_type_string);
117         value = json_object_get_string(object);
118     }
119
120     template<typename T>
121     static void fromJsonObject(json_object* object, std::vector<T>& value)
122     {
123         checkType(object, json_type_array);
124         int length = json_object_array_length(object);
125         value.resize(static_cast<size_t>(length));
126         for (int i = 0; i < length; ++i) {
127             fromJsonObject(json_object_array_get_idx(object, i), value[static_cast<size_t>(i)]);
128         }
129     }
130
131     template<typename T, class = typename std::enable_if<isVisitable<T>::value>::type>
132     static void fromJsonObject(json_object* object, T& value)
133     {
134         checkType(object, json_type_object);
135         FromJsonVisitor visitor(object);
136         value.accept(visitor);
137     }
138 };
139
140 } // namespace config
141
142 #endif // CONFIG_FROM_JSON_VISITOR_HPP