From bb674f609e25e5f7a216f9c30676c4381c2f99c9 Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Wed, 26 Nov 2014 15:11:51 +0100 Subject: [PATCH] Added possibility to declare union in config file [Bug/Feature] Possibility to declare something like union in config file [Cause] Necessity to create vector with element of more than one type [Solution] Added macro CONFIG_DECLARE_OPTIONS [Verification] Build, install, run scs tests Change-Id: I094eb63f5cda6435836b3d76674d3cad5f89fe14 --- src/config/fields-union.hpp | 158 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 src/config/fields-union.hpp diff --git a/src/config/fields-union.hpp b/src/config/fields-union.hpp new file mode 100644 index 0000000..8f4d997 --- /dev/null +++ b/src/config/fields-union.hpp @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Mateusz Malicki (m.malicki2@samsung.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +/** + * @file + * @author Mateusz Malicki (m.malicki2@samsung.com) + * @brief Macros for declare configuration fields + */ + +#ifndef CONFIG_FIELDS_UNION_HPP +#define CONFIG_FIELDS_UNION_HPP + +#include "config/fields.hpp" +#include +#include + +/** + * Use this macro to declare and register config fields + * + * Example: + * struct Foo { + * std::string bar; + * + * CONFIG_REGISTER + * ( + * bar, + * ) + * }; + * + * struct Config + * { + * CONFIG_DECLARE_UNION + * ( + * Foo, + * int + * ) + * }; + * + * Example of valid configuration: + * 1. { + * "type": "Foo", + * "value": { "bar": "some string" } + * } + * 2. { + * "type": "int", + * "value": 1 + * } + * + * + * Usage: + * Config config; + * if (config.is()) { + * Foo& foo = config.as(); + * // ... + * } + * if (config.is())) { + * int field = config.as(); + * // ... + * } + */ + + +#define CONFIG_DECLARE_UNION(...) \ + struct TypeWrapperBase \ + { \ + virtual ~TypeWrapperBase() {} \ + }; \ + \ + template \ + struct TypeWrapper : TypeWrapperBase \ + { \ + Class value; \ + ~TypeWrapper() {} \ + }; \ + \ + std::unique_ptr mConfigDeclareField__; \ + \ + template \ + void accept(Visitor v) { \ + std::string name; \ + v.visit("type", name); \ + visitOption(v, name); \ + } \ + \ + template \ + void accept(Visitor v) const { \ + const std::string name = getOptionName(); \ + if (!name.empty()) { \ + v.visit("type", name); \ + visitOption(v, name); \ + } else { \ + /* Unsupported type in config file */ \ + } \ + } \ + \ + template \ + void visitOption(Visitor& v, const std::string& name) { \ + GENERATE_CODE(GENERATE_UNION_VISIT__, __VA_ARGS__) \ + } \ + template \ + void visitOption(Visitor& v, const std::string& name) const { \ + GENERATE_CODE(GENERATE_UNION_VISIT_CONST__, __VA_ARGS__) \ + } \ + std::string getOptionName() const { \ + GENERATE_CODE(GENERATE_UNION_NAME__, __VA_ARGS__) \ + return std::string(); \ + } \ + \ + template \ + bool is() const { \ + return dynamic_cast*>(mConfigDeclareField__.get()) != NULL; \ + } \ + template \ + Type& as() { \ + assert(mConfigDeclareField__.get()); \ + return dynamic_cast&>(*mConfigDeclareField__.get()).value; \ + } \ + template \ + const Type& as() const { \ + assert(mConfigDeclareField__.get()); \ + return dynamic_cast&>(*mConfigDeclareField__.get()).value; \ + } + +#define GENERATE_CODE(MACRO, ...) \ + BOOST_PP_LIST_FOR_EACH(MACRO, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)) + +#define GENERATE_UNION_VISIT__(r, _, TYPE_) \ + if (#TYPE_ == name) { \ + mConfigDeclareField__.reset(new TypeWrapper()); \ + v.visit("value", as()); \ + } + +#define GENERATE_UNION_VISIT_CONST__(r, _, TYPE_) \ + if (#TYPE_ == name) { \ + v.visit("value", as()); \ + } + +#define GENERATE_UNION_NAME__(r, _, TYPE_) \ + if (is()) { \ + return #TYPE_; \ + } + +#endif /* CONFIG_FIELDS_UNION_HPP */ -- 2.7.4