Added GVariant visitor
[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 <cassert>
35 #include <glib.h>
36
37 namespace config {
38
39 class FromGVariantVisitor {
40 public:
41     explicit FromGVariantVisitor(GVariant* variant)
42     {
43         //Assume that the visited object is not a union
44         checkType(variant, G_VARIANT_TYPE_TUPLE);
45         mIter = g_variant_iter_new(variant);
46     }
47
48     FromGVariantVisitor(const FromGVariantVisitor& visitor)
49         : mIter(g_variant_iter_copy(visitor.mIter))
50     {
51     }
52
53     ~FromGVariantVisitor()
54     {
55         g_variant_iter_free(mIter);
56     }
57
58     FromGVariantVisitor& operator=(const FromGVariantVisitor&) = delete;
59
60     template<typename T>
61     void visit(const std::string& name, T& value)
62     {
63         GVariant* child = g_variant_iter_next_value(mIter);
64         if (child == NULL) {
65             throw config::ConfigException(
66                 "GVariant doesn't match with config. Can't set  '" + name + "'");
67         }
68         fromGVariant(child, value);
69         g_variant_unref(child);
70     }
71
72 private:
73     GVariantIter* mIter;
74
75     explicit FromGVariantVisitor(GVariant* variant, bool isUnion)
76     {
77         if (isUnion) {
78             checkType(variant, G_VARIANT_TYPE_VARIANT);
79             variant = g_variant_get_variant(variant);
80         }
81         checkType(variant, G_VARIANT_TYPE_TUPLE);
82         mIter = g_variant_iter_new(variant);
83     }
84
85     static void checkType(GVariant* object, const GVariantType* type)
86     {
87         if (!g_variant_is_of_type(object, type)) {
88             throw ConfigException("Invalid field type");
89         }
90     }
91
92     static void fromGVariant(GVariant* object, int& value)
93     {
94         checkType(object, G_VARIANT_TYPE_INT32);
95         value = g_variant_get_int32(object);
96     }
97
98     static void fromGVariant(GVariant* object, std::int64_t& value)
99     {
100         checkType(object, G_VARIANT_TYPE_INT64);
101         value = g_variant_get_int64(object);
102     }
103
104     static void fromGVariant(GVariant* object, bool& value)
105     {
106         checkType(object, G_VARIANT_TYPE_BOOLEAN);
107         value = g_variant_get_boolean(object);
108     }
109
110     static void fromGVariant(GVariant* object, double& value)
111     {
112         checkType(object, G_VARIANT_TYPE_DOUBLE);
113         value = g_variant_get_double(object);
114     }
115
116     static void fromGVariant(GVariant* object, std::string& value)
117     {
118         checkType(object, G_VARIANT_TYPE_STRING);
119         value = g_variant_get_string(object, NULL);
120     }
121
122     template<typename T>
123     static void fromGVariant(GVariant* object, std::vector<T>& value)
124     {
125         checkType(object, G_VARIANT_TYPE_ARRAY);
126         GVariantIter iter;
127         g_variant_iter_init(&iter, object);
128         int length = g_variant_iter_n_children(&iter);
129         value.resize(static_cast<size_t>(length));
130         for (int i = 0; i < length; ++i) {
131             GVariant* child = g_variant_iter_next_value(&iter);
132             assert(child != NULL);
133             fromGVariant(child, value[static_cast<size_t>(i)]);
134             g_variant_unref(child);
135         }
136     }
137
138     template<typename T>
139     static typename std::enable_if<isVisitable<T>::value>::type
140     fromGVariant(GVariant* object, T& value)
141     {
142         FromGVariantVisitor visitor(object, isUnion<T>::value);
143         value.accept(visitor);
144     }
145
146 };
147
148 } // namespace config
149
150 #endif // CONFIG_FROM_GVARIANT_VISITOR_HPP