2 * Copyright (c) 2014 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 Macros for declare configuration fields
25 #ifndef CONFIG_FIELDS_UNION_HPP
26 #define CONFIG_FIELDS_UNION_HPP
28 #include "config/fields.hpp"
29 #include "config/exception.hpp"
32 #include <boost/any.hpp>
36 * Use this macro to declare and register config fields
50 * CONFIG_DECLARE_UNION
57 * Example of valid configuration:
60 * "value": { "bar": "some string" }
71 * if (config.isSet()) {
72 * if (config.is<Foo>()) {
73 * Foo& foo = config.as<Foo>();
76 * if (config.is<int>())) {
77 * int field = config.as<int>();
81 * // Config is not set
82 * Foo foo({"some string"});
84 * config.set(std::move(foo)); //< copy sic!
85 * config.set(Foo({"some string"}));
89 class DisbaleMoveAnyWrapper : public boost::any
92 DisbaleMoveAnyWrapper() {}
93 DisbaleMoveAnyWrapper(const DisbaleMoveAnyWrapper& any)
94 : boost::any(static_cast<const boost::any&>(any)) {};
95 DisbaleMoveAnyWrapper& operator=(DisbaleMoveAnyWrapper&& any) = delete;
96 DisbaleMoveAnyWrapper& operator=(const DisbaleMoveAnyWrapper& any) {
97 static_cast<boost::any&>(*this) = static_cast<const boost::any&>(any);
102 #define CONFIG_DECLARE_UNION(...) \
104 DisbaleMoveAnyWrapper mConfigDeclareField; \
106 template<typename Visitor> \
107 void visitOption(Visitor& v, const std::string& name) { \
108 GENERATE_CODE(GENERATE_UNION_VISIT__, __VA_ARGS__) \
109 throw config::ConfigException("Union type error. Unsupported type"); \
111 template<typename Visitor> \
112 void visitOption(Visitor& v, const std::string& name) const { \
113 GENERATE_CODE(GENERATE_UNION_VISIT_CONST__, __VA_ARGS__) \
114 throw config::ConfigException("Union type error. Unsupported type"); \
116 std::string getOptionName() const { \
117 GENERATE_CODE(GENERATE_UNION_NAME__, __VA_ARGS__) \
118 return std::string(); \
120 boost::any& getHolder() { \
121 return static_cast<boost::any&>(mConfigDeclareField); \
123 const boost::any& getHolder() const { \
124 return static_cast<const boost::any&>(mConfigDeclareField); \
128 template<typename Visitor> \
129 void accept(Visitor v) { \
131 v.visit("type", name); \
132 visitOption(v, name); \
135 template<typename Visitor> \
136 void accept(Visitor v) const { \
137 const std::string name = getOptionName(); \
138 assert(!name.empty() && "Type is not set"); \
139 v.visit("type", name); \
140 visitOption(v, name); \
143 template<typename Type> \
145 return boost::any_cast<Type>(&getHolder()) != NULL; \
147 template<typename Type> \
148 typename std::enable_if<!std::is_const<Type>::value, Type>::type& as() { \
149 assert(!getHolder().empty()); \
150 return boost::any_cast<Type&>(getHolder()); \
152 template<typename Type> \
153 const Type& as() const { \
154 assert(!getHolder().empty()); \
155 return boost::any_cast<const Type&>(getHolder()); \
158 return !getOptionName().empty(); \
160 template<typename Type> \
161 Type& set(const Type& src) { \
162 getHolder() = std::forward<const Type>(src); \
163 assert(!getOptionName().empty() && "Unsupported type"); \
167 #define GENERATE_CODE(MACRO, ...) \
168 BOOST_PP_LIST_FOR_EACH(MACRO, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__))
170 #define GENERATE_UNION_VISIT__(r, _, TYPE_) \
171 if (#TYPE_ == name) { \
172 v.visit("value", set(std::move(TYPE_()))); \
176 #define GENERATE_UNION_VISIT_CONST__(r, _, TYPE_) \
177 if (#TYPE_ == name) { \
178 v.visit("value", as<const TYPE_>()); \
182 #define GENERATE_UNION_NAME__(r, _, TYPE_) \
187 #endif /* CONFIG_FIELDS_UNION_HPP */