Support for uints
[archive/platform/core/system/libConfig.git] / src / config / from-gvariant-visitor.hpp
1 /*
2  *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Mateusz Malicki (m.malicki2@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  Mateusz Malicki (m.malicki2@samsung.com)
22  * @brief   GVariant visitor
23  */
24
25 #ifndef CONFIG_FROM_GVARIANT_VISITOR_HPP
26 #define CONFIG_FROM_GVARIANT_VISITOR_HPP
27
28 #include "config/is-visitable.hpp"
29 #include "config/exception.hpp"
30 #include "config/is-union.hpp"
31
32 #include <string>
33 #include <vector>
34 #include <memory>
35 #include <cassert>
36 #include <glib.h>
37
38 namespace config {
39
40 class FromGVariantVisitor {
41 public:
42     explicit FromGVariantVisitor(GVariant* variant)
43     {
44         //Assume that the visited object is not a union
45         checkType(variant, G_VARIANT_TYPE_TUPLE);
46         mIter = g_variant_iter_new(variant);
47     }
48
49     FromGVariantVisitor(const FromGVariantVisitor& visitor)
50         : mIter(g_variant_iter_copy(visitor.mIter))
51     {
52     }
53
54     ~FromGVariantVisitor()
55     {
56         g_variant_iter_free(mIter);
57     }
58
59     FromGVariantVisitor& operator=(const FromGVariantVisitor&) = delete;
60
61     template<typename T>
62     void visit(const std::string& name, T& value)
63     {
64         auto child = makeUnique(g_variant_iter_next_value(mIter));
65         if (!child) {
66             throw config::ConfigException(
67                 "GVariant doesn't match with config. Can't set  '" + name + "'");
68         }
69         fromGVariant(child.get(), value);
70     }
71
72 private:
73     GVariantIter* mIter;
74
75     static std::unique_ptr<GVariant, decltype(&g_variant_unref)> makeUnique(GVariant* variant)
76     {
77         return std::unique_ptr<GVariant, decltype(&g_variant_unref)>(variant, g_variant_unref);
78     }
79
80     static void checkType(GVariant* object, const GVariantType* type)
81     {
82         if (!g_variant_is_of_type(object, type)) {
83             throw ConfigException("Invalid field type");
84         }
85     }
86
87     static void fromGVariant(GVariant* object, std::int32_t& value)
88     {
89         checkType(object, G_VARIANT_TYPE_INT32);
90         value = g_variant_get_int32(object);
91     }
92
93     static void fromGVariant(GVariant* object, std::int64_t& value)
94     {
95         checkType(object, G_VARIANT_TYPE_INT64);
96         value = g_variant_get_int64(object);
97     }
98
99     static void fromGVariant(GVariant* object, std::uint32_t& value)
100     {
101         checkType(object, G_VARIANT_TYPE_UINT32);
102         value = g_variant_get_uint32(object);
103     }
104
105     static void fromGVariant(GVariant* object, std::uint64_t& value)
106     {
107         checkType(object, G_VARIANT_TYPE_UINT64);
108         value = g_variant_get_uint64(object);
109     }
110
111     static void fromGVariant(GVariant* object, bool& value)
112     {
113         checkType(object, G_VARIANT_TYPE_BOOLEAN);
114         value = g_variant_get_boolean(object);
115     }
116
117     static void fromGVariant(GVariant* object, double& value)
118     {
119         checkType(object, G_VARIANT_TYPE_DOUBLE);
120         value = g_variant_get_double(object);
121     }
122
123     static void fromGVariant(GVariant* object, std::string& value)
124     {
125         checkType(object, G_VARIANT_TYPE_STRING);
126         value = g_variant_get_string(object, NULL);
127     }
128
129     template<typename T>
130     static void fromGVariant(GVariant* object, std::vector<T>& value)
131     {
132         checkType(object, G_VARIANT_TYPE_ARRAY);
133         GVariantIter iter;
134         g_variant_iter_init(&iter, object);
135         int length = g_variant_iter_n_children(&iter);
136         value.resize(static_cast<size_t>(length));
137         for (int i = 0; i < length; ++i) {
138             auto child = makeUnique(g_variant_iter_next_value(&iter));
139             assert(child);
140             fromGVariant(child.get(), value[static_cast<size_t>(i)]);
141         }
142     }
143
144     template<typename T>
145     static typename std::enable_if<isUnion<T>::value>::type
146     fromGVariant(GVariant* object, T& value)
147     {
148         checkType(object, G_VARIANT_TYPE_VARIANT);
149         auto inner = makeUnique(g_variant_get_variant(object));
150
151         FromGVariantVisitor visitor(inner.get());
152         value.accept(visitor);
153     }
154
155     template<typename T>
156     static typename std::enable_if<isVisitable<T>::value && !isUnion<T>::value>::type
157     fromGVariant(GVariant* object, T& value)
158     {
159         FromGVariantVisitor visitor(object);
160         value.accept(visitor);
161     }
162
163 };
164
165 } // namespace config
166
167 #endif // CONFIG_FROM_GVARIANT_VISITOR_HPP