a06b6c290875f7baadef12a148653fadcbb7231e
[senf.git] / senf / Utils / Console / ParsedCommand.mpp
1 // $Id$
2 //
3 // Copyright (C) 2008
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief ParsedCommand Boost.Preprocesser external iteration include */
25
26 #if !BOOST_PP_IS_ITERATING && !defined(MPP_ParsedCommand_)
27 #define MPP_ParsedCommand_ 1
28
29 // Custom includes
30 #include <boost/preprocessor/iteration/iterate.hpp>
31 #include <boost/preprocessor/repetition/enum_trailing.hpp>
32 #include <boost/preprocessor/repetition/enum_params.hpp>
33 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
34 #include <boost/preprocessor/cat.hpp>
35 #include <boost/preprocessor/arithmetic/inc.hpp>
36 #include <boost/preprocessor/arithmetic/sub.hpp>
37 #include <boost/preprocessor/repetition/repeat.hpp>
38 #include <boost/type_traits/remove_reference.hpp>
39 #include <boost/type_traits/remove_const.hpp>
40 #include <boost/bind.hpp>
41 #include <boost/mpl/vector.hpp>
42 #include <boost/mpl/at.hpp>
43 #include "senf/Utils/IgnoreValue.hh"
44
45 //-///////////////////////////mpp.p////////////////////////////////////////
46 #elif BOOST_PP_IS_ITERATING //-////////////////////////////////////////////
47 //-////////////////////////////////////////////////////////////////////////
48 // Local Macros
49
50 #define mpp_ArgTypeN(n) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(n)), _type)
51 #define mpp_ArgN(n) BOOST_PP_CAT(arg, BOOST_PP_INC(n))
52
53 #define mpp_TrailingArgTypes_(z,n,d) typename traits::mpp_ArgTypeN(n)
54 #define mpp_TrailingArgTypes() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_TrailingArgTypes_, _ )
55
56 #define mpp_ArgTypes_(z,n,d) mpp_ArgTypeN(n)
57 #define mpp_ArgTypes() BOOST_PP_ENUM( BOOST_PP_ITERATION(), mpp_ArgTypes_, _ )
58
59 #define mpp_Args_(z,n,d) mpp_ArgN(n)
60 #define mpp_TrailingArgs() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_Args_, _ )
61
62 #define mpp_BindArgs_(z,n,d) BOOST_PP_CAT( _, BOOST_PP_INC(BOOST_PP_INC(n)))
63 #define mpp_TrailingBindArgs() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_BindArgs_, _ )
64
65 //-////////////////////////////////////////////////////////////////////////
66 #if BOOST_PP_ITERATION_FLAGS()==1 //-//////////////////////////////////////
67 //-////////////////////////////////////////////////////////////////////////
68
69 // Header file (.hh)
70
71 template <class FunctionTraits, class ReturnValue>
72 class ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >
73     : public ParsedCommandOverloadBase
74 {
75 public:
76     typedef boost::intrusive_ptr<ParsedCommandOverload> ptr;
77     typedef FunctionTraits traits;
78     typedef boost::function<typename traits::result_type(std::ostream &
79                                                          mpp_TrailingArgTypes())> Function;
80     typedef typename senf::remove_cvref<typename traits::result_type>::type result_type;
81     typedef boost::function<void (result_type const &, std::ostream &)> Formatter;
82
83 #   define mpp_l(z,n,d)                                                                           \
84         typedef typename senf::remove_cvref< typename traits::mpp_ArgTypeN(n) >::type             \
85             mpp_ArgTypeN(n);
86     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
87 #   undef mpp_l
88
89     typedef boost::mpl::vector< mpp_ArgTypes() > arg_types;
90
91     static ptr create(Function fn);
92
93     void formatter(Formatter f);
94
95     using ParsedCommandOverloadBase::arg;
96     template <unsigned n>
97     detail::ArgumentInfo<typename boost::mpl::at_c<arg_types, n>::type> & arg() const;
98
99     void function(Function fn);
100
101 protected:
102
103 private:
104     ParsedCommandOverload(Function fn);
105
106     virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
107         const;
108
109     Function function_;
110     Formatter formatter_;
111 };
112
113 template <class FunctionTraits>
114 class ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >
115     : public ParsedCommandOverloadBase
116 {
117 public:
118     typedef boost::intrusive_ptr<ParsedCommandOverload> ptr;
119     typedef FunctionTraits traits;
120     typedef boost::function<typename traits::result_type(std::ostream &
121                                                          mpp_TrailingArgTypes())> Function;
122     typedef void result_type;
123
124 #   define mpp_l(z,n,d)                                                                           \
125         typedef typename senf::remove_cvref< typename traits::mpp_ArgTypeN(n) >::type             \
126             mpp_ArgTypeN(n);
127     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
128 #   undef mpp_l
129
130     typedef boost::mpl::vector< mpp_ArgTypes() > arg_types;
131
132     static ptr create(Function fn);
133
134     using ParsedCommandOverloadBase::arg;
135     template <unsigned n>
136     detail::ArgumentInfo<typename boost::mpl::at_c<arg_types, n>::type> & arg() const;
137
138     void function(Function fn);
139
140 protected:
141
142 private:
143     ParsedCommandOverload(Function fn);
144
145     virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
146         const;
147
148     Function function_;
149 };
150
151 //-////////////////////////////////////////////////////////////////////////
152 #elif BOOST_PP_ITERATION_FLAGS()==2 //-////////////////////////////////////
153 //-////////////////////////////////////////////////////////////////////////
154
155 // inline template implementation (.cti)
156
157 template <class FunctionTraits, class ReturnValue>
158 prefix_ typename senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::ptr
159 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
160 create(Function fn)
161 {
162     return ptr(new ParsedCommandOverload(fn));
163 }
164
165 template <class FunctionTraits, class ReturnValue>
166 void
167 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
168 formatter(Formatter f)
169 {
170     formatter_ = f;
171 }
172
173 template <class FunctionTraits, class ReturnValue>
174 template <unsigned n>
175 senf::console::detail::ArgumentInfo<
176     typename boost::mpl::at_c<
177         typename senf::console::ParsedCommandOverload<
178             FunctionTraits, ReturnValue, BOOST_PP_ITERATION()>::arg_types,
179         n>::type> &
180 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
181 arg() const
182 {
183     return static_cast< detail::ArgumentInfo<
184         typename boost::mpl::at_c<arg_types, n>::type > & >(arg(n));
185 }
186
187 template <class FunctionTraits, class ReturnValue>
188 void
189 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
190 function(Function fn)
191 {
192     function_ = fn;
193 }
194
195 template <class FunctionTraits, class ReturnValue>
196 prefix_
197 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION()>::
198 ParsedCommandOverload(Function fn)
199     : function_ (fn)
200 {
201 #   define mpp_l(z,n,d) addParameter< mpp_ArgTypeN(n) >();
202     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
203 #   undef mpp_l
204 }
205
206 template <class FunctionTraits>
207 prefix_ typename senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::ptr
208 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
209 create(Function fn)
210 {
211     return ptr(new ParsedCommandOverload(fn));
212 }
213
214 template <class FunctionTraits>
215 template <unsigned n>
216 senf::console::detail::ArgumentInfo<
217     typename boost::mpl::at_c<
218         typename senf::console::ParsedCommandOverload<
219             FunctionTraits, void, BOOST_PP_ITERATION()>::arg_types,
220         n>::type> &
221 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
222 arg() const
223 {
224     return static_cast< detail::ArgumentInfo<
225         typename boost::mpl::at_c<arg_types, n>::type > & >(arg(n));
226 }
227
228 template <class FunctionTraits>
229 void
230 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
231 function(Function fn)
232 {
233     function_ = fn;
234 }
235
236 template <class FunctionTraits>
237 prefix_
238 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
239 ParsedCommandOverload(Function fn)
240     : function_ (fn)
241 {
242 #   define mpp_l(z,n,d) addParameter< mpp_ArgTypeN(n) >();
243     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
244 #   undef mpp_l
245 }
246
247 //-////////////////////////////////////////////////////////////////////////
248 #elif BOOST_PP_ITERATION_FLAGS()==3 //-////////////////////////////////////
249 //-////////////////////////////////////////////////////////////////////////
250
251 // non-inline template implementation (.ct)
252
253 template <class FunctionTraits, class ReturnValue>
254 prefix_ void senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
255 v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
256     const
257 {
258     // We NEED to know the number of arguments beforehand so we can assign default values
259     // correctly ... hrmpf ...
260     unsigned nArgs ( std::distance(command.arguments().begin(), command.arguments().end()) );
261     if ( nArgs > BOOST_PP_ITERATION() )
262         throw SyntaxErrorException("invalid number of arguments");
263     int nDefaults ( BOOST_PP_ITERATION() - nArgs );
264     senf::IGNORE( nDefaults );
265
266     typedef typename boost::range_reverse_iterator<const ParseCommandInfo::ArgumentsRange>::type
267         riterator;
268     riterator i (boost::rbegin(command.arguments()));
269     riterator const i_end (boost::rend(command.arguments()));
270
271 #   define mpp_l(z,n,d)                                                                           \
272         mpp_ArgTypeN(n) mpp_ArgN(n) (arg<n>().defaultValue);                                      \
273         if (! arg(n).hasDefault || nDefaults-- <= 0) {                                            \
274             if (i == i_end)                                                                       \
275                 throw SyntaxErrorException("invalid number of arguments");                        \
276             if (arg<n>().parser)                                                                  \
277                 arg<n>().parser( *(i++), mpp_ArgN(n) );                                           \
278             else                                                                                  \
279                 ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) );                  \
280         }
281 #   define mpp_l_(z,n,d) mpp_l(z, BOOST_PP_SUB(BOOST_PP_DEC(BOOST_PP_ITERATION()), n), d)
282     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l_, _ )
283 #   undef mpp_l
284 #   undef mpp_l_
285
286     ReturnValue rvv (function_(os mpp_TrailingArgs()));
287     rv = rvv;
288     if (formatter_)
289         formatter_(rvv, os);
290     else
291         ReturnValueTraits<result_type>::format(rvv, os);
292     os << "\n";
293 }
294
295 template <class FunctionTraits>
296 prefix_ void senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
297 v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
298     const
299 {
300     // We NEED to know the number of arguments beforehand so we can assign default values
301     // correctly ... hrmpf ...
302     unsigned nArgs ( std::distance(command.arguments().begin(), command.arguments().end()) );
303     if ( nArgs > BOOST_PP_ITERATION() )
304         throw SyntaxErrorException("invalid number of arguments");
305     int nDefaults ( BOOST_PP_ITERATION() - nArgs );
306     senf::IGNORE( nDefaults );
307
308     typedef typename boost::range_reverse_iterator<const ParseCommandInfo::ArgumentsRange>::type
309         riterator;
310     riterator i (boost::rbegin(command.arguments()));
311     riterator const i_end (boost::rend(command.arguments()));
312
313 #   define mpp_l(z,n,d)                                                                           \
314         mpp_ArgTypeN(n) mpp_ArgN(n) (arg<n>().defaultValue);                                      \
315         if (! arg(n).hasDefault || nDefaults-- <= 0) {                                            \
316             if (i == i_end)                                                                       \
317                 throw SyntaxErrorException("invalid number of arguments");                        \
318             if (arg<n>().parser)                                                                  \
319                 arg<n>().parser( *(i++), mpp_ArgN(n) );                                           \
320             else                                                                                  \
321                 ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) );                  \
322         }
323 #   define mpp_l_(z,n,d) mpp_l(z, BOOST_PP_SUB(BOOST_PP_DEC(BOOST_PP_ITERATION()), n), d)
324     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l_, _ )
325 #   undef mpp_l
326 #   undef mpp_l_
327
328     function_(os mpp_TrailingArgs());
329 }
330
331 //-////////////////////////////////////////////////////////////////////////
332 #elif BOOST_PP_ITERATION_FLAGS()==4 //-////////////////////////////////////
333 //-////////////////////////////////////////////////////////////////////////
334
335 // CreateParsedCommandOverload
336
337 template <class Traits>
338 struct CreateParsedCommandOverload<Traits, true, BOOST_PP_ITERATION()>
339 {
340     typedef typename Traits::traits traits;
341
342     template <class Function>
343     static typename senf::console::ParsedCommandOverload<traits>::ptr create(Function fn)
344         {
345             return senf::console::ParsedCommandOverload<traits>::create(
346                 boost::bind(fn  mpp_TrailingBindArgs()) );
347         }
348
349 };
350
351 //-////////////////////////////////////////////////////////////////////////
352 #elif BOOST_PP_ITERATION_FLAGS()==5 //-////////////////////////////////////
353 //-////////////////////////////////////////////////////////////////////////
354
355 // Create keyword arg forwarding functions
356
357 template <BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), class A ) >
358 next_type arg ( BOOST_PP_ENUM_BINARY_PARAMS( BOOST_PP_ITERATION(), A, const & a ),
359                 typename arg_params::match< BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), A ) >::type
360                     kw = arg_params()) {
361     return argInfo( kw(BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), a )) );
362 }
363
364 //-////////////////////////////////////////////////////////////////////////
365 #endif //-/////////////////////////////////////////////////////////////////
366 //-////////////////////////////////////////////////////////////////////////
367 // Undefine local Macros
368
369 #undef mpp_TrailingBindArgs
370 #undef mpp_BindArgs_
371
372 #undef mpp_TrailingArgs
373 #undef mpp_Args_
374
375 #undef mpp_ArgTypes
376 #undef mpp_ArgTypes_
377
378 #undef mpp_TrailingArgTypes
379 #undef mpp_TrailingArgTypes_
380
381 #undef mpp_ArgN
382 #undef mpp_ArgTypeN
383
384 //-////////////////////////////////////////////////////////////////////////
385 #endif //-/////////////////////////////////////////////////////////////////
386 //-///////////////////////////mpp.e////////////////////////////////////////
387
388 \f
389 // Local Variables:
390 // mode: c++
391 // fill-column: 100
392 // comment-column: 40
393 // c-file-style: "senf"
394 // indent-tabs-mode: nil
395 // ispell-local-dictionary: "american"
396 // compile-command: "scons -u test"
397 // End: