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>
35 * Use this macro to declare and register config fields
49 * CONFIG_DECLARE_UNION
56 * Example of valid configuration:
59 * "value": { "bar": "some string" }
70 * if (config.isSet()) {
71 * if (config.is<Foo>()) {
72 * Foo& foo = config.as<Foo>();
75 * if (config.is<int>())) {
76 * int field = config.as<int>();
80 * // Config is not set
81 * Foo foo({"some string"});
83 * config.set(std::move(foo)); //< copy sic!
84 * config.set(Foo({"some string"}));
88 class DisbaleMoveAnyWrapper : public boost::any
91 DisbaleMoveAnyWrapper() {}
92 DisbaleMoveAnyWrapper(const DisbaleMoveAnyWrapper& any)
93 : boost::any(static_cast<const boost::any&>(any)) {};
94 DisbaleMoveAnyWrapper& operator=(DisbaleMoveAnyWrapper&& any) = delete;
95 DisbaleMoveAnyWrapper& operator=(const DisbaleMoveAnyWrapper& any) {
96 static_cast<boost::any&>(*this) = static_cast<const boost::any&>(any);
101 #define CONFIG_DECLARE_UNION(...) \
103 DisbaleMoveAnyWrapper mConfigDeclareField; \
105 template<typename Visitor> \
106 void visitOption(Visitor& v, const std::string& name) { \
107 GENERATE_CODE(GENERATE_UNION_VISIT__, __VA_ARGS__) \
108 throw config::ConfigException("Union type error. Unsupported type"); \
110 template<typename Visitor> \
111 void visitOption(Visitor& v, const std::string& name) const { \
112 GENERATE_CODE(GENERATE_UNION_VISIT_CONST__, __VA_ARGS__) \
113 throw config::ConfigException("Union type error. Unsupported type"); \
115 std::string getOptionName() const { \
116 GENERATE_CODE(GENERATE_UNION_NAME__, __VA_ARGS__) \
117 return std::string(); \
119 boost::any& getHolder() { \
120 return static_cast<boost::any&>(mConfigDeclareField); \
122 const boost::any& getHolder() const { \
123 return static_cast<const boost::any&>(mConfigDeclareField); \
127 template<typename Visitor> \
128 void accept(Visitor v) { \
130 v.visit("type", name); \
131 visitOption(v, name); \
134 template<typename Visitor> \
135 void accept(Visitor v) const { \
136 const std::string name = getOptionName(); \
137 if (name.empty()) { \
138 throw config::ConfigException("Type is not set"); \
140 v.visit("type", name); \
141 visitOption(v, name); \
144 template<typename Type> \
146 return boost::any_cast<Type>(&getHolder()) != NULL; \
148 template<typename Type> \
149 typename std::enable_if<!std::is_const<Type>::value, Type>::type& as() { \
150 if (getHolder().empty()) { \
151 throw config::ConfigException("Type is not set"); \
153 return boost::any_cast<Type&>(getHolder()); \
155 template<typename Type> \
156 const Type& as() const { \
157 if (getHolder().empty()) { \
158 throw config::ConfigException("Type is not set"); \
160 return boost::any_cast<const Type&>(getHolder()); \
163 return !getOptionName().empty(); \
165 template<typename Type> \
166 Type& set(const Type& src) { \
167 getHolder() = std::forward<const Type>(src); \
168 if (getOptionName().empty()) { \
169 throw config::ConfigException("Unsupported type"); \
174 #define GENERATE_CODE(MACRO, ...) \
175 BOOST_PP_LIST_FOR_EACH(MACRO, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__))
177 #define GENERATE_UNION_VISIT__(r, _, TYPE_) \
178 if (#TYPE_ == name) { \
179 v.visit("value", set(std::move(TYPE_()))); \
183 #define GENERATE_UNION_VISIT_CONST__(r, _, TYPE_) \
184 if (#TYPE_ == name) { \
185 v.visit("value", as<const TYPE_>()); \
189 #define GENERATE_UNION_NAME__(r, _, TYPE_) \
194 #endif /* CONFIG_FIELDS_UNION_HPP */