2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
15 \brief Traits internal header */
17 #ifndef IH_SENF_Scheduler_Console_Traits_
18 #define IH_SENF_Scheduler_Console_Traits_ 1
23 #include <boost/preprocessor/seq/for_each.hpp>
24 #include <boost/preprocessor/stringize.hpp>
25 #include <boost/preprocessor/facilities/empty.hpp>
26 #include <boost/preprocessor/if.hpp>
27 #include <boost/bimap.hpp>
28 #include <boost/assign/list_inserter.hpp>
29 #include <boost/algorithm/string/case_conv.hpp>
30 #include <boost/mpl/if.hpp>
31 #include <senf/Utils/preprocessor.hh>
33 //-/////////////////////////////////////////////////////////////////////////////////////////////////
38 template <class _> struct ArgumentTraits;
39 template <class _> struct ReturnValueTraits;
43 template <class CharT>
44 struct MatchingShortType
45 : public boost::mpl::if_c<std::numeric_limits<CharT>::is_signed,short,unsigned short>
48 template <class CharT>
49 struct CharArgumentTraits
50 : public ArgumentTraits<typename MatchingShortType<CharT>::type>
52 typedef ArgumentTraits<typename MatchingShortType<CharT>::type> base;
54 static void parse(ParseCommandInfo::TokensRange const & tokens, CharT & out);
55 static std::string description();
58 template <class CharT>
59 struct CharReturnValueTraits
60 : public ReturnValueTraits<typename MatchingShortType<CharT>::type>
69 EnumFormatter(T v) : value(v) {}
72 inline std::ostream & operator<<(std::ostream & os, EnumFormatter<T> const & enumFormatter)
74 senf_console_format_value(enumFormatter.value, os);
81 bool operator()(std::string const & left, std::string const & right) const
82 { return boost::algorithm::to_lower_copy(left)
83 < boost::algorithm::to_lower_copy(right); }
86 typedef boost::bimap<boost::bimaps::set_of<std::string, StringILess>, long> EnumTable;
88 long parseEnum(EnumTable const & table, ParseCommandInfo::TokensRange const & tokens);
89 std::string formatEnum(EnumTable const & table, long value);
91 # define SENF_CONSOLE_REGISTER_ENUM_ELT(r,d,e) \
92 BOOST_PP_IF( SENF_CONSOLE_REGISTER_ENUM_HASKEY(e), \
93 SENF_CONSOLE_REGISTER_ENUM_WITHKEY, \
94 SENF_CONSOLE_REGISTER_ENUM_NOKEY )(d, e)
96 # define SENF_CONSOLE_REGISTER_ENUM_GOBBLE__key(k,e)
97 # define SENF_CONSOLE_REGISTER_ENUM_GET_KEY__key(k,e) k
98 # define SENF_CONSOLE_REGISTER_ENUM_GET_ENUM__key(k,e) e
99 # define SENF_CONSOLE_REGISTER_ENUM_HASKEY(e) \
100 BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_CONSOLE_REGISTER_ENUM_GOBBLE__, e) )
102 # define SENF_CONSOLE_REGISTER_ENUM_KEY_GETENUM(e) \
103 SENF_CAT_RECURS2(SENF_CONSOLE_REGISTER_ENUM_GET_ENUM__, e)
104 # define SENF_CONSOLE_REGISTER_ENUM_KEY_GETKEY(e) \
105 SENF_CAT_RECURS3(SENF_CONSOLE_REGISTER_ENUM_GET_KEY__, e)
107 # define SENF_CONSOLE_REGISTER_ENUM_NOKEY(prefix, e) \
108 ( BOOST_PP_STRINGIZE(e), static_cast<long>(prefix e) )
110 # define SENF_CONSOLE_REGISTER_ENUM_WITHKEY(prefix, e) \
111 ( SENF_CONSOLE_REGISTER_ENUM_KEY_GETKEY(e), \
112 static_cast<long>(prefix SENF_CONSOLE_REGISTER_ENUM_KEY_GETENUM(e)) )
115 # define SENF_CONSOLE_REGISTER_ENUM_(Prefix, Scope, Type, Values) \
116 inline senf::console::detail::EnumTable & senf_console_enum_table(Prefix Type) \
118 static senf::console::detail::EnumTable table; \
120 boost::assign::insert(table) \
121 BOOST_PP_SEQ_FOR_EACH( \
122 SENF_CONSOLE_REGISTER_ENUM_ELT, Prefix Scope, Values ); \
125 inline void senf_console_parse_argument( \
126 senf::console::ParseCommandInfo::TokensRange const & tokens, Prefix Type & out) \
128 out = static_cast<Prefix Type>( \
129 senf::console::detail::parseEnum( \
130 senf_console_enum_table( Prefix Type() ), tokens) ); \
132 inline void senf_console_format_value(Prefix Type value, std::ostream & os) \
134 os << senf::console::detail::formatEnum( \
135 senf_console_enum_table( Prefix Type() ), static_cast<long>(value) ); \
137 inline senf::console::detail::EnumFormatter<Prefix Type> \
138 senf_console_format_enum(Prefix Type value) \
140 return senf::console::detail::EnumFormatter<Prefix Type>(value); \
144 # define SENF_CONSOLE_PARSE_TUPLE_ELT(r, d, member) \
145 senf::console::parse( *(arg++), out.member );
147 # define SENF_CONSOLE_FORMAT_TUPLE_ELT(r, d, i, member) \
148 os << BOOST_PP_IF(i, " ", "") \
149 << senf::console::str(value.member); \
151 # define SENF_CONSOLE_PARSE_AS_TUPLE_(Type, Members) \
153 namespace console { \
155 struct ArgumentTraits<Type> \
158 static bool const singleToken = false; \
159 static void parse(ParseCommandInfo::TokensRange const & tokens, Type & out) \
161 senf::console::CheckedArgumentIteratorWrapper arg (tokens); \
162 BOOST_PP_SEQ_FOR_EACH( SENF_CONSOLE_PARSE_TUPLE_ELT, _, Members ); \
164 static std::string description() \
166 return prettyBaseName(typeid(Type)); \
168 static std::string str(Type const & value) \
170 std::stringstream ss; \
171 senf::console::format(value, ss); \
177 # define SENF_CONSOLE_FORMAT_AS_TUPLE_(Type, Members) \
179 namespace console { \
181 struct ReturnValueTraits<Type> \
184 static void format(Type const & value, std::ostream & os) \
187 BOOST_PP_SEQ_FOR_EACH_I( SENF_CONSOLE_FORMAT_TUPLE_ELT, , Members ); \
193 # define SENF_CONSOLE_PARSE_AS_MAP_ELT(r, d, i, KeyMemberTuple) \
194 if (key == BOOST_PP_TUPLE_ELEM(2, 0, KeyMemberTuple)) { \
195 senf::console::parse( *(arg++), out. BOOST_PP_TUPLE_ELEM(2, 1, KeyMemberTuple)); \
196 keyBitmap &= ~(1 << i); \
200 # define SENF_CONSOLE_PARSE_AS_MAP_ERROR_ELT(r, d, i, KeyMemberTuple) \
201 if (ffs(keyBitmap) == i+1) \
202 throw SyntaxErrorException("Key missing: ") \
203 << BOOST_PP_TUPLE_ELEM(2, 0, KeyMemberTuple);
205 # define SENF_CONSOLE_FORMAT_AS_MAP_ELT(r, d, i, KeyMemberTuple) \
206 os << BOOST_PP_IF(i, " ", "") \
207 << senf::console::str(BOOST_PP_TUPLE_ELEM(2, 0, KeyMemberTuple)) << '=' \
208 << senf::console::str(value.BOOST_PP_TUPLE_ELEM(2, 1, KeyMemberTuple));
210 # define SENF_CONSOLE_PARSE_AS_MAP_(Type, KeyMemberTuples) \
212 namespace console { \
214 struct ArgumentTraits<Type> \
217 static bool const singleToken = false; \
218 static void parse(ParseCommandInfo::TokensRange const & tokens, Type & out) \
220 int keyBitmap = (1 << BOOST_PP_SEQ_SIZE(KeyMemberTuples)) - 1; \
222 CheckedArgumentIteratorWrapper arg (tokens); \
224 senf::console::parse( *(arg++), key ); \
225 ParseCommandInfo::TokensRange sep (*(arg++)); \
226 if (sep.size() != 1 || sep[0].type() != Token::OtherPunctuation \
227 || sep[0].value() != "=") \
228 throw SyntaxErrorException("'=' expected"); \
229 BOOST_PP_SEQ_FOR_EACH_I( \
230 SENF_CONSOLE_PARSE_AS_MAP_ELT, _, KeyMemberTuples ); \
231 throw SyntaxErrorException("Unknown Key: " + key); \
233 if (keyBitmap != 0) { \
234 BOOST_PP_SEQ_FOR_EACH_I( \
235 SENF_CONSOLE_PARSE_AS_MAP_ERROR_ELT, _, KeyMemberTuples ); \
238 static std::string description() \
240 return prettyBaseName(typeid(Type)); \
242 static std::string str(Type const & value) \
244 std::stringstream ss; \
245 senf::console::format(value, ss); \
251 # define SENF_CONSOLE_FORMAT_AS_MAP_(Type, KeyMemberTuples) \
253 namespace console { \
255 struct ReturnValueTraits<Type> \
258 static void format(Type const & value, std::ostream & os) \
261 BOOST_PP_SEQ_FOR_EACH_I( \
262 SENF_CONSOLE_FORMAT_AS_MAP_ELT, _, KeyMemberTuples ); \
272 //-/////////////////////////////////////////////////////////////////////////////////////////////////
279 // comment-column: 40
280 // c-file-style: "senf"
281 // indent-tabs-mode: nil
282 // ispell-local-dictionary: "american"
283 // compile-command: "scons -u test"