ParsedCommand.mpp
Go to the documentation of this file.
1 //
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
6 //
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
11 //
12 
13 
14 /** \file
15  \brief ParsedCommand Boost.Preprocesser external iteration include */
16 
17 #if !BOOST_PP_IS_ITERATING && !defined(MPP_ParsedCommand_)
18 #define MPP_ParsedCommand_ 1
19 
20 // Custom includes
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"
35 
36 //-///////////////////////////mpp.p////////////////////////////////////////
37 #elif BOOST_PP_IS_ITERATING //-////////////////////////////////////////////
38 //-////////////////////////////////////////////////////////////////////////
39 // Local Macros
40 
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))
43 
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_, _ )
46 
47 #define mpp_ArgTypes_(z,n,d) mpp_ArgTypeN(n)
48 #define mpp_ArgTypes() BOOST_PP_ENUM( BOOST_PP_ITERATION(), mpp_ArgTypes_, _ )
49 
50 #define mpp_Args_(z,n,d) mpp_ArgN(n)
51 #define mpp_TrailingArgs() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_Args_, _ )
52 
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_, _ )
55 
56 //-////////////////////////////////////////////////////////////////////////
57 #if BOOST_PP_ITERATION_FLAGS()==1 //-//////////////////////////////////////
58 //-////////////////////////////////////////////////////////////////////////
59 
60 // Header file (.hh)
61 
62 template <class FunctionTraits, class ReturnValue>
63 class ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >
64  : public ParsedCommandOverloadBase
65 {
66 public:
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;
73 
74 # define mpp_l(z,n,d) \
75  typedef typename senf::remove_cvref< typename traits::mpp_ArgTypeN(n) >::type \
76  mpp_ArgTypeN(n);
77  BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
78 # undef mpp_l
79 
80  typedef boost::mpl::vector< mpp_ArgTypes() > arg_types;
81 
82  static ptr create(Function fn);
83 
84  void formatter(Formatter f);
85 
86  using ParsedCommandOverloadBase::arg;
87  template <unsigned n>
88  detail::ArgumentInfo<typename boost::mpl::at_c<arg_types, n>::type> & arg() const;
89 
90  void function(Function fn);
91 
92 protected:
93 
94 private:
95  ParsedCommandOverload(Function fn);
96 
97  virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
98  const;
99 
100  Function function_;
101  Formatter formatter_;
102 };
103 
104 template <class FunctionTraits>
105 class ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >
106  : public ParsedCommandOverloadBase
107 {
108 public:
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;
114 
115 # define mpp_l(z,n,d) \
116  typedef typename senf::remove_cvref< typename traits::mpp_ArgTypeN(n) >::type \
117  mpp_ArgTypeN(n);
118  BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
119 # undef mpp_l
120 
121  typedef boost::mpl::vector< mpp_ArgTypes() > arg_types;
122 
123  static ptr create(Function fn);
124 
125  using ParsedCommandOverloadBase::arg;
126  template <unsigned n>
127  detail::ArgumentInfo<typename boost::mpl::at_c<arg_types, n>::type> & arg() const;
128 
129  void function(Function fn);
130 
131 protected:
132 
133 private:
134  ParsedCommandOverload(Function fn);
135 
136  virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
137  const;
138 
139  Function function_;
140 };
141 
142 //-////////////////////////////////////////////////////////////////////////
143 #elif BOOST_PP_ITERATION_FLAGS()==2 //-////////////////////////////////////
144 //-////////////////////////////////////////////////////////////////////////
145 
146 // inline template implementation (.cti)
147 
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() >::
151 create(Function fn)
152 {
153  return ptr(new ParsedCommandOverload(fn));
154 }
155 
156 template <class FunctionTraits, class ReturnValue>
157 void
158 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
159 formatter(Formatter f)
160 {
161  formatter_ = f;
162 }
163 
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,
170  n>::type> &
171 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
172 arg() const
173 {
174  return static_cast< detail::ArgumentInfo<
175  typename boost::mpl::at_c<arg_types, n>::type > & >(arg(n));
176 }
177 
178 template <class FunctionTraits, class ReturnValue>
179 void
180 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
181 function(Function fn)
182 {
183  function_ = fn;
184 }
185 
186 template <class FunctionTraits, class ReturnValue>
187 prefix_
188 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION()>::
189 ParsedCommandOverload(Function fn)
190  : function_ (fn)
191 {
192 # define mpp_l(z,n,d) addParameter< mpp_ArgTypeN(n) >();
193  BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
194 # undef mpp_l
195 }
196 
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() >::
200 create(Function fn)
201 {
202  return ptr(new ParsedCommandOverload(fn));
203 }
204 
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,
211  n>::type> &
212 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
213 arg() const
214 {
215  return static_cast< detail::ArgumentInfo<
216  typename boost::mpl::at_c<arg_types, n>::type > & >(arg(n));
217 }
218 
219 template <class FunctionTraits>
220 void
221 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
222 function(Function fn)
223 {
224  function_ = fn;
225 }
226 
227 template <class FunctionTraits>
228 prefix_
229 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
230 ParsedCommandOverload(Function fn)
231  : function_ (fn)
232 {
233 # define mpp_l(z,n,d) addParameter< mpp_ArgTypeN(n) >();
234  BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
235 # undef mpp_l
236 }
237 
238 //-////////////////////////////////////////////////////////////////////////
239 #elif BOOST_PP_ITERATION_FLAGS()==3 //-////////////////////////////////////
240 //-////////////////////////////////////////////////////////////////////////
241 
242 // non-inline template implementation (.ct)
243 
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)
247  const
248 {
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 );
256 
257  typedef typename boost::range_reverse_iterator<const ParseCommandInfo::ArgumentsRange>::type
258  riterator;
259  riterator i (boost::rbegin(command.arguments()));
260  riterator const i_end (boost::rend(command.arguments()));
261 
262 # define mpp_l(z,n,d) \
263  mpp_ArgTypeN(n) mpp_ArgN(n) (arg<n>().defaultValue); \
264  if (! arg(n).hasDefault || nDefaults-- <= 0) { \
265  if (i == i_end) \
266  throw SyntaxErrorException("invalid number of arguments"); \
267  if (arg<n>().parser) \
268  arg<n>().parser( *(i++), mpp_ArgN(n) ); \
269  else \
270  ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) ); \
271  }
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_, _ )
274 # undef mpp_l
275 # undef mpp_l_
276 
277  ReturnValue rvv (function_(os mpp_TrailingArgs()));
278  rv = rvv;
279  if (formatter_)
280  formatter_(rvv, os);
281  else
282  ReturnValueTraits<result_type>::format(rvv, os);
283  os << "\n";
284 }
285 
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)
289  const
290 {
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 );
298 
299  typedef typename boost::range_reverse_iterator<const ParseCommandInfo::ArgumentsRange>::type
300  riterator;
301  riterator i (boost::rbegin(command.arguments()));
302  riterator const i_end (boost::rend(command.arguments()));
303 
304 # define mpp_l(z,n,d) \
305  mpp_ArgTypeN(n) mpp_ArgN(n) (arg<n>().defaultValue); \
306  if (! arg(n).hasDefault || nDefaults-- <= 0) { \
307  if (i == i_end) \
308  throw SyntaxErrorException("invalid number of arguments"); \
309  if (arg<n>().parser) \
310  arg<n>().parser( *(i++), mpp_ArgN(n) ); \
311  else \
312  ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) ); \
313  }
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_, _ )
316 # undef mpp_l
317 # undef mpp_l_
318 
319  function_(os mpp_TrailingArgs());
320 }
321 
322 //-////////////////////////////////////////////////////////////////////////
323 #elif BOOST_PP_ITERATION_FLAGS()==4 //-////////////////////////////////////
324 //-////////////////////////////////////////////////////////////////////////
325 
326 // CreateParsedCommandOverload
327 
328 template <class Traits>
329 struct CreateParsedCommandOverload<Traits, true, BOOST_PP_ITERATION()>
330 {
331  typedef typename Traits::traits traits;
332 
333  template <class Function>
334  static typename senf::console::ParsedCommandOverload<traits>::ptr create(Function fn)
335  {
336  return senf::console::ParsedCommandOverload<traits>::create(
337  boost::bind(fn mpp_TrailingBindArgs()) );
338  }
339 
340 };
341 
342 //-////////////////////////////////////////////////////////////////////////
343 #elif BOOST_PP_ITERATION_FLAGS()==5 //-////////////////////////////////////
344 //-////////////////////////////////////////////////////////////////////////
345 
346 // Create keyword arg forwarding functions
347 
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
351  kw = arg_params()) {
352  return argInfo( kw(BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), a )) );
353 }
354 
355 //-////////////////////////////////////////////////////////////////////////
356 #endif //-/////////////////////////////////////////////////////////////////
357 //-////////////////////////////////////////////////////////////////////////
358 // Undefine local Macros
359 
360 #undef mpp_TrailingBindArgs
361 #undef mpp_BindArgs_
362 
363 #undef mpp_TrailingArgs
364 #undef mpp_Args_
365 
366 #undef mpp_ArgTypes
367 #undef mpp_ArgTypes_
368 
369 #undef mpp_TrailingArgTypes
370 #undef mpp_TrailingArgTypes_
371 
372 #undef mpp_ArgN
373 #undef mpp_ArgTypeN
374 
375 //-////////////////////////////////////////////////////////////////////////
376 #endif //-/////////////////////////////////////////////////////////////////
377 //-///////////////////////////mpp.e////////////////////////////////////////
378 
379 
380 // Local Variables:
381 // mode: c++
382 // fill-column: 100
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"
388 // End: