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 ParsedCommand Boost.Preprocesser external iteration include */
17 #if !BOOST_PP_IS_ITERATING && !defined(MPP_ParsedCommand_)
18 #define MPP_ParsedCommand_ 1
21 #include <boost/preprocessor/iteration/iterate.hpp>
22 #include <boost/preprocessor/repetition/enum_trailing.hpp>
23 #include <boost/preprocessor/repetition/enum_params.hpp>
24 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
25 #include <boost/preprocessor/cat.hpp>
26 #include <boost/preprocessor/arithmetic/inc.hpp>
27 #include <boost/preprocessor/arithmetic/sub.hpp>
28 #include <boost/preprocessor/repetition/repeat.hpp>
29 #include <boost/type_traits/remove_reference.hpp>
30 #include <boost/type_traits/remove_const.hpp>
31 #include <boost/bind.hpp>
32 #include <boost/mpl/vector.hpp>
33 #include <boost/mpl/at.hpp>
34 #include "senf/Utils/IgnoreValue.hh"
36 //-///////////////////////////mpp.p////////////////////////////////////////
37 #elif BOOST_PP_IS_ITERATING //-////////////////////////////////////////////
38 //-////////////////////////////////////////////////////////////////////////
41 #define mpp_ArgTypeN(n) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(n)), _type)
42 #define mpp_ArgN(n) BOOST_PP_CAT(arg, BOOST_PP_INC(n))
44 #define mpp_TrailingArgTypes_(z,n,d) typename traits::mpp_ArgTypeN(n)
45 #define mpp_TrailingArgTypes() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_TrailingArgTypes_, _ )
47 #define mpp_ArgTypes_(z,n,d) mpp_ArgTypeN(n)
48 #define mpp_ArgTypes() BOOST_PP_ENUM( BOOST_PP_ITERATION(), mpp_ArgTypes_, _ )
50 #define mpp_Args_(z,n,d) mpp_ArgN(n)
51 #define mpp_TrailingArgs() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_Args_, _ )
53 #define mpp_BindArgs_(z,n,d) BOOST_PP_CAT( _, BOOST_PP_INC(BOOST_PP_INC(n)))
54 #define mpp_TrailingBindArgs() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_BindArgs_, _ )
56 //-////////////////////////////////////////////////////////////////////////
57 #if BOOST_PP_ITERATION_FLAGS()==1 //-//////////////////////////////////////
58 //-////////////////////////////////////////////////////////////////////////
62 template <class FunctionTraits, class ReturnValue>
63 class ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >
64 : public ParsedCommandOverloadBase
67 typedef boost::intrusive_ptr<ParsedCommandOverload> ptr;
68 typedef FunctionTraits traits;
69 typedef boost::function<typename traits::result_type(std::ostream &
70 mpp_TrailingArgTypes())> Function;
71 typedef typename senf::remove_cvref<typename traits::result_type>::type result_type;
72 typedef boost::function<void (result_type const &, std::ostream &)> Formatter;
74 # define mpp_l(z,n,d) \
75 typedef typename senf::remove_cvref< typename traits::mpp_ArgTypeN(n) >::type \
77 BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
80 typedef boost::mpl::vector< mpp_ArgTypes() > arg_types;
82 static ptr create(Function fn);
84 void formatter(Formatter f);
86 using ParsedCommandOverloadBase::arg;
88 detail::ArgumentInfo<typename boost::mpl::at_c<arg_types, n>::type> & arg() const;
90 void function(Function fn);
95 ParsedCommandOverload(Function fn);
97 virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
101 Formatter formatter_;
104 template <class FunctionTraits>
105 class ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >
106 : public ParsedCommandOverloadBase
109 typedef boost::intrusive_ptr<ParsedCommandOverload> ptr;
110 typedef FunctionTraits traits;
111 typedef boost::function<typename traits::result_type(std::ostream &
112 mpp_TrailingArgTypes())> Function;
113 typedef void result_type;
115 # define mpp_l(z,n,d) \
116 typedef typename senf::remove_cvref< typename traits::mpp_ArgTypeN(n) >::type \
118 BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
121 typedef boost::mpl::vector< mpp_ArgTypes() > arg_types;
123 static ptr create(Function fn);
125 using ParsedCommandOverloadBase::arg;
126 template <unsigned n>
127 detail::ArgumentInfo<typename boost::mpl::at_c<arg_types, n>::type> & arg() const;
129 void function(Function fn);
134 ParsedCommandOverload(Function fn);
136 virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
142 //-////////////////////////////////////////////////////////////////////////
143 #elif BOOST_PP_ITERATION_FLAGS()==2 //-////////////////////////////////////
144 //-////////////////////////////////////////////////////////////////////////
146 // inline template implementation (.cti)
148 template <class FunctionTraits, class ReturnValue>
149 prefix_ typename senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::ptr
150 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
153 return ptr(new ParsedCommandOverload(fn));
156 template <class FunctionTraits, class ReturnValue>
158 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
159 formatter(Formatter f)
164 template <class FunctionTraits, class ReturnValue>
165 template <unsigned n>
166 senf::console::detail::ArgumentInfo<
167 typename boost::mpl::at_c<
168 typename senf::console::ParsedCommandOverload<
169 FunctionTraits, ReturnValue, BOOST_PP_ITERATION()>::arg_types,
171 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
174 return static_cast< detail::ArgumentInfo<
175 typename boost::mpl::at_c<arg_types, n>::type > & >(arg(n));
178 template <class FunctionTraits, class ReturnValue>
180 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
181 function(Function fn)
186 template <class FunctionTraits, class ReturnValue>
188 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION()>::
189 ParsedCommandOverload(Function fn)
192 # define mpp_l(z,n,d) addParameter< mpp_ArgTypeN(n) >();
193 BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
197 template <class FunctionTraits>
198 prefix_ typename senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::ptr
199 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
202 return ptr(new ParsedCommandOverload(fn));
205 template <class FunctionTraits>
206 template <unsigned n>
207 senf::console::detail::ArgumentInfo<
208 typename boost::mpl::at_c<
209 typename senf::console::ParsedCommandOverload<
210 FunctionTraits, void, BOOST_PP_ITERATION()>::arg_types,
212 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
215 return static_cast< detail::ArgumentInfo<
216 typename boost::mpl::at_c<arg_types, n>::type > & >(arg(n));
219 template <class FunctionTraits>
221 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
222 function(Function fn)
227 template <class FunctionTraits>
229 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
230 ParsedCommandOverload(Function fn)
233 # define mpp_l(z,n,d) addParameter< mpp_ArgTypeN(n) >();
234 BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
238 //-////////////////////////////////////////////////////////////////////////
239 #elif BOOST_PP_ITERATION_FLAGS()==3 //-////////////////////////////////////
240 //-////////////////////////////////////////////////////////////////////////
242 // non-inline template implementation (.ct)
244 template <class FunctionTraits, class ReturnValue>
245 prefix_ void senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
246 v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
249 // We NEED to know the number of arguments beforehand so we can assign default values
250 // correctly ... hrmpf ...
251 unsigned nArgs ( std::distance(command.arguments().begin(), command.arguments().end()) );
252 if ( nArgs > BOOST_PP_ITERATION() )
253 throw SyntaxErrorException("invalid number of arguments");
254 int nDefaults ( BOOST_PP_ITERATION() - nArgs );
255 senf::IGNORE( nDefaults );
257 typedef typename boost::range_reverse_iterator<const ParseCommandInfo::ArgumentsRange>::type
259 riterator i (boost::rbegin(command.arguments()));
260 riterator const i_end (boost::rend(command.arguments()));
262 # define mpp_l(z,n,d) \
263 mpp_ArgTypeN(n) mpp_ArgN(n) (arg<n>().defaultValue); \
264 if (! arg(n).hasDefault || nDefaults-- <= 0) { \
266 throw SyntaxErrorException("invalid number of arguments"); \
267 if (arg<n>().parser) \
268 arg<n>().parser( *(i++), mpp_ArgN(n) ); \
270 ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) ); \
272 # define mpp_l_(z,n,d) mpp_l(z, BOOST_PP_SUB(BOOST_PP_DEC(BOOST_PP_ITERATION()), n), d)
273 BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l_, _ )
277 ReturnValue rvv (function_(os mpp_TrailingArgs()));
282 ReturnValueTraits<result_type>::format(rvv, os);
286 template <class FunctionTraits>
287 prefix_ void senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
288 v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
291 // We NEED to know the number of arguments beforehand so we can assign default values
292 // correctly ... hrmpf ...
293 unsigned nArgs ( std::distance(command.arguments().begin(), command.arguments().end()) );
294 if ( nArgs > BOOST_PP_ITERATION() )
295 throw SyntaxErrorException("invalid number of arguments");
296 int nDefaults ( BOOST_PP_ITERATION() - nArgs );
297 senf::IGNORE( nDefaults );
299 typedef typename boost::range_reverse_iterator<const ParseCommandInfo::ArgumentsRange>::type
301 riterator i (boost::rbegin(command.arguments()));
302 riterator const i_end (boost::rend(command.arguments()));
304 # define mpp_l(z,n,d) \
305 mpp_ArgTypeN(n) mpp_ArgN(n) (arg<n>().defaultValue); \
306 if (! arg(n).hasDefault || nDefaults-- <= 0) { \
308 throw SyntaxErrorException("invalid number of arguments"); \
309 if (arg<n>().parser) \
310 arg<n>().parser( *(i++), mpp_ArgN(n) ); \
312 ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) ); \
314 # define mpp_l_(z,n,d) mpp_l(z, BOOST_PP_SUB(BOOST_PP_DEC(BOOST_PP_ITERATION()), n), d)
315 BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l_, _ )
319 function_(os mpp_TrailingArgs());
322 //-////////////////////////////////////////////////////////////////////////
323 #elif BOOST_PP_ITERATION_FLAGS()==4 //-////////////////////////////////////
324 //-////////////////////////////////////////////////////////////////////////
326 // CreateParsedCommandOverload
328 template <class Traits>
329 struct CreateParsedCommandOverload<Traits, true, BOOST_PP_ITERATION()>
331 typedef typename Traits::traits traits;
333 template <class Function>
334 static typename senf::console::ParsedCommandOverload<traits>::ptr create(Function fn)
336 return senf::console::ParsedCommandOverload<traits>::create(
337 boost::bind(fn mpp_TrailingBindArgs()) );
342 //-////////////////////////////////////////////////////////////////////////
343 #elif BOOST_PP_ITERATION_FLAGS()==5 //-////////////////////////////////////
344 //-////////////////////////////////////////////////////////////////////////
346 // Create keyword arg forwarding functions
348 template <BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), class A ) >
349 next_type arg ( BOOST_PP_ENUM_BINARY_PARAMS( BOOST_PP_ITERATION(), A, const & a ),
350 typename arg_params::match< BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), A ) >::type
352 return argInfo( kw(BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), a )) );
355 //-////////////////////////////////////////////////////////////////////////
356 #endif //-/////////////////////////////////////////////////////////////////
357 //-////////////////////////////////////////////////////////////////////////
358 // Undefine local Macros
360 #undef mpp_TrailingBindArgs
363 #undef mpp_TrailingArgs
369 #undef mpp_TrailingArgTypes
370 #undef mpp_TrailingArgTypes_
375 //-////////////////////////////////////////////////////////////////////////
376 #endif //-/////////////////////////////////////////////////////////////////
377 //-///////////////////////////mpp.e////////////////////////////////////////
383 // comment-column: 40
384 // c-file-style: "senf"
385 // indent-tabs-mode: nil
386 // ispell-local-dictionary: "american"
387 // compile-command: "scons -u test"