cc19a8c3a8058e2e1c9527fac76e90a09c19223e
[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     template<class T>
59     void visit(const std::string& name, T& value)
60     {
61         json_object* object = nullptr;
62         if (!json_object_object_get_ex(mObject, name.c_str(), &object)) {
63             throw ConfigException("Missing field '" + name + "'");
64         }
65         fromJsonObject(object, value);
66     }
67
68 private:
69     json_object* mObject;
70
71     FromJsonVisitor& operator=(const FromJsonVisitor&) = delete;
72
73     explicit FromJsonVisitor(json_object* object)
74         : mObject(json_object_get(object))
75     {
76     }
77
78     static void checkType(json_object* object, json_type type)
79     {
80         if (type != json_object_get_type(object)) {
81             throw ConfigException("Invalid field type");
82         }
83     }
84
85     static void fromJsonObject(json_object* object, int& value)
86     {
87         checkType(object, json_type_int);
88         std::int64_t value64 = json_object_get_int64(object);
89         if (value64 > INT32_MAX || value64 < INT32_MIN) {
90             throw ConfigException("Value out of range");
91         }
92         value = static_cast<int>(value64);
93     }
94
95     static void fromJsonObject(json_object* object, std::int64_t& value)
96     {
97         checkType(object, json_type_int);
98         value = json_object_get_int64(object);
99     }
100
101     static void fromJsonObject(json_object* object, bool& value)
102     {
103         checkType(object, json_type_boolean);
104         value = json_object_get_boolean(object);
105     }
106
107     static void fromJsonObject(json_object* object, double& value)
108     {
109         checkType(object, json_type_double);
110         value = json_object_get_double(object);
111     }
112
113     static void fromJsonObject(json_object* object, std::string& value)
114     {
115         checkType(object, json_type_string);
116         value = json_object_get_string(object);
117     }
118
119     template<class T>
120     static void fromJsonObject(json_object* object, std::vector<T>& value)
121     {
122         checkType(object, json_type_array);
123         int length = json_object_array_length(object);
124         value.resize(static_cast<size_t>(length));
125         for (int i = 0; i < length; ++i) {
126             fromJsonObject(json_object_array_get_idx(object, i), value[static_cast<size_t>(i)]);
127         }
128     }
129
130     template<class T, class = typename std::enable_if<isVisitable<T>::value>::type>
131     static void fromJsonObject(json_object* object, T& value)
132     {
133         checkType(object, json_type_object);
134         FromJsonVisitor visitor(object);
135         value.accept(visitor);
136     }
137 };
138
139 } // namespace config
140
141 #endif // CONFIG_FROM_JSON_VISITOR_HPP