2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Mateusz Malicki (m.malicki2@samsung.com)
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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
21 * @author Mateusz Malicki (m.malicki2@samsung.com)
22 * @brief GVariant visitor
25 #ifndef CONFIG_FROM_GVARIANT_VISITOR_HPP
26 #define CONFIG_FROM_GVARIANT_VISITOR_HPP
28 #include "config/is-visitable.hpp"
29 #include "config/exception.hpp"
30 #include "config/is-union.hpp"
40 class FromGVariantVisitor {
42 explicit FromGVariantVisitor(GVariant* variant)
44 //Assume that the visited object is not a union
45 checkType(variant, G_VARIANT_TYPE_TUPLE);
46 mIter = g_variant_iter_new(variant);
49 FromGVariantVisitor(const FromGVariantVisitor& visitor)
50 : mIter(g_variant_iter_copy(visitor.mIter))
54 ~FromGVariantVisitor()
56 g_variant_iter_free(mIter);
59 FromGVariantVisitor& operator=(const FromGVariantVisitor&) = delete;
62 void visit(const std::string& name, T& value)
64 auto child = makeUnique(g_variant_iter_next_value(mIter));
66 throw config::ConfigException(
67 "GVariant doesn't match with config. Can't set '" + name + "'");
69 fromGVariant(child.get(), value);
75 static std::unique_ptr<GVariant, decltype(&g_variant_unref)> makeUnique(GVariant* variant)
77 return std::unique_ptr<GVariant, decltype(&g_variant_unref)>(variant, g_variant_unref);
80 static void checkType(GVariant* object, const GVariantType* type)
82 if (!g_variant_is_of_type(object, type)) {
83 throw ConfigException("Invalid field type");
87 static void fromGVariant(GVariant* object, std::int32_t& value)
89 checkType(object, G_VARIANT_TYPE_INT32);
90 value = g_variant_get_int32(object);
93 static void fromGVariant(GVariant* object, std::int64_t& value)
95 checkType(object, G_VARIANT_TYPE_INT64);
96 value = g_variant_get_int64(object);
99 static void fromGVariant(GVariant* object, std::uint32_t& value)
101 checkType(object, G_VARIANT_TYPE_UINT32);
102 value = g_variant_get_uint32(object);
105 static void fromGVariant(GVariant* object, std::uint64_t& value)
107 checkType(object, G_VARIANT_TYPE_UINT64);
108 value = g_variant_get_uint64(object);
111 static void fromGVariant(GVariant* object, bool& value)
113 checkType(object, G_VARIANT_TYPE_BOOLEAN);
114 value = g_variant_get_boolean(object);
117 static void fromGVariant(GVariant* object, double& value)
119 checkType(object, G_VARIANT_TYPE_DOUBLE);
120 value = g_variant_get_double(object);
123 static void fromGVariant(GVariant* object, std::string& value)
125 checkType(object, G_VARIANT_TYPE_STRING);
126 value = g_variant_get_string(object, NULL);
130 static void fromGVariant(GVariant* object, std::vector<T>& value)
132 checkType(object, G_VARIANT_TYPE_ARRAY);
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));
140 fromGVariant(child.get(), value[static_cast<size_t>(i)]);
145 static typename std::enable_if<isUnion<T>::value>::type
146 fromGVariant(GVariant* object, T& value)
148 checkType(object, G_VARIANT_TYPE_VARIANT);
149 auto inner = makeUnique(g_variant_get_variant(object));
151 FromGVariantVisitor visitor(inner.get());
152 value.accept(visitor);
156 static typename std::enable_if<isVisitable<T>::value && !isUnion<T>::value>::type
157 fromGVariant(GVariant* object, T& value)
159 FromGVariantVisitor visitor(object);
160 value.accept(visitor);
165 } // namespace config
167 #endif // CONFIG_FROM_GVARIANT_VISITOR_HPP