Move Console from Scheduler into Utils
[senf.git] / 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
44 // ///////////////////////////mpp.p////////////////////////////////////////
45 #elif BOOST_PP_IS_ITERATING // ////////////////////////////////////////////
46 // ////////////////////////////////////////////////////////////////////////
47 // Local Macros
48
49 #define mpp_ArgTypeN(n) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(n)), _type)
50 #define mpp_ArgN(n) BOOST_PP_CAT(arg, BOOST_PP_INC(n))
51
52 #define mpp_TrailingArgTypes_(z,n,d) typename traits::mpp_ArgTypeN(n)
53 #define mpp_TrailingArgTypes() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_TrailingArgTypes_, _ )
54
55 #define mpp_ArgTypes_(z,n,d) mpp_ArgTypeN(n)
56 #define mpp_ArgTypes() BOOST_PP_ENUM( BOOST_PP_ITERATION(), mpp_ArgTypes_, _ )
57
58 #define mpp_Args_(z,n,d) mpp_ArgN(n)
59 #define mpp_TrailingArgs() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_Args_, _ )
60
61 #define mpp_BindArgs_(z,n,d) BOOST_PP_CAT( _, BOOST_PP_INC(BOOST_PP_INC(n)))
62 #define mpp_TrailingBindArgs() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_BindArgs_, _ )
63
64 // ////////////////////////////////////////////////////////////////////////
65 #if BOOST_PP_ITERATION_FLAGS()==1 // //////////////////////////////////////
66 // ////////////////////////////////////////////////////////////////////////
67
68 // Header file (.hh)
69
70 template <class FunctionTraits, class ReturnValue>
71 class ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >
72     : public ParsedCommandOverloadBase
73 {
74 public:
75     typedef boost::intrusive_ptr<ParsedCommandOverload> ptr;
76     typedef FunctionTraits traits;
77     typedef boost::function<typename traits::result_type(std::ostream &
78                                                          mpp_TrailingArgTypes())> Function;
79     typedef typename senf::remove_cvref<typename traits::result_type>::type result_type;
80     typedef boost::function<void (result_type const &, std::ostream &)> Formatter;
81
82 #   define mpp_l(z,n,d)                                                                           \
83         typedef typename senf::remove_cvref< typename traits::mpp_ArgTypeN(n) >::type             \
84             mpp_ArgTypeN(n);
85     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
86 #   undef mpp_l
87
88     typedef boost::mpl::vector< mpp_ArgTypes() > arg_types;
89
90     static ptr create(Function fn);
91
92     void formatter(Formatter f);
93
94     using ParsedCommandOverloadBase::arg;
95     template <unsigned n>
96     detail::ArgumentInfo<typename boost::mpl::at_c<arg_types, n>::type> & arg() const;
97
98     void function(Function fn);
99
100 protected:
101
102 private:
103     ParsedCommandOverload(Function fn);
104
105     virtual void v_execute(std::ostream & os, ParseCommandInfo const & command) const;
106
107     Function function_;
108     Formatter formatter_;
109 };
110
111 template <class FunctionTraits>
112 class ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >
113     : public ParsedCommandOverloadBase
114 {
115 public:
116     typedef boost::intrusive_ptr<ParsedCommandOverload> ptr;
117     typedef FunctionTraits traits;
118     typedef boost::function<typename traits::result_type(std::ostream &
119                                                          mpp_TrailingArgTypes())> Function;
120     typedef void result_type;
121
122 #   define mpp_l(z,n,d)                                                                           \
123         typedef typename senf::remove_cvref< typename traits::mpp_ArgTypeN(n) >::type             \
124             mpp_ArgTypeN(n);
125     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
126 #   undef mpp_l
127
128     typedef boost::mpl::vector< mpp_ArgTypes() > arg_types;
129
130     static ptr create(Function fn);
131
132     using ParsedCommandOverloadBase::arg;
133     template <unsigned n>
134     detail::ArgumentInfo<typename boost::mpl::at_c<arg_types, n>::type> & arg() const;
135
136     void function(Function fn);
137
138 protected:
139
140 private:
141     ParsedCommandOverload(Function fn);
142
143     virtual void v_execute(std::ostream & os, ParseCommandInfo const & command) const;
144
145     Function function_;
146 };
147
148 // ////////////////////////////////////////////////////////////////////////
149 #elif BOOST_PP_ITERATION_FLAGS()==2 // ////////////////////////////////////
150 // ////////////////////////////////////////////////////////////////////////
151
152 // inline template implementation (.cti)
153
154 template <class FunctionTraits, class ReturnValue>
155 prefix_ typename senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::ptr
156 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
157 create(Function fn)
158 {
159     return ptr(new ParsedCommandOverload(fn));
160 }
161
162 template <class FunctionTraits, class ReturnValue>
163 void
164 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
165 formatter(Formatter f)
166 {
167     formatter_ = f;
168 }
169
170 template <class FunctionTraits, class ReturnValue>
171 template <unsigned n>
172 senf::console::detail::ArgumentInfo<
173     typename boost::mpl::at_c<
174         typename senf::console::ParsedCommandOverload<
175             FunctionTraits, ReturnValue, BOOST_PP_ITERATION()>::arg_types,
176         n>::type> &
177 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
178 arg() const
179 {
180     return static_cast< detail::ArgumentInfo< 
181         typename boost::mpl::at_c<arg_types, n>::type > & >(arg(n));
182 }
183
184 template <class FunctionTraits, class ReturnValue>
185 void
186 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
187 function(Function fn)
188 {
189     function_ = fn;
190 }
191
192 template <class FunctionTraits, class ReturnValue>
193 prefix_
194 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION()>::
195 ParsedCommandOverload(Function fn)
196     : function_ (fn) 
197 {
198 #   define mpp_l(z,n,d) addParameter< mpp_ArgTypeN(n) >();
199     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
200 #   undef mpp_l
201 }
202
203 template <class FunctionTraits>
204 prefix_ typename senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::ptr
205 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
206 create(Function fn)
207 {
208     return ptr(new ParsedCommandOverload(fn));
209 }
210
211 template <class FunctionTraits>
212 template <unsigned n>
213 senf::console::detail::ArgumentInfo<
214     typename boost::mpl::at_c<
215         typename senf::console::ParsedCommandOverload<
216             FunctionTraits, void, BOOST_PP_ITERATION()>::arg_types,
217         n>::type> &
218 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
219 arg() const
220 {
221     return static_cast< detail::ArgumentInfo< 
222         typename boost::mpl::at_c<arg_types, n>::type > & >(arg(n));
223 }
224
225 template <class FunctionTraits>
226 void
227 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
228 function(Function fn)
229 {
230     function_ = fn;
231 }
232
233 template <class FunctionTraits>
234 prefix_
235 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
236 ParsedCommandOverload(Function fn)
237     : function_ (fn) 
238 {
239 #   define mpp_l(z,n,d) addParameter< mpp_ArgTypeN(n) >();
240     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
241 #   undef mpp_l
242 }
243
244 // ////////////////////////////////////////////////////////////////////////
245 #elif BOOST_PP_ITERATION_FLAGS()==3 // ////////////////////////////////////
246 // ////////////////////////////////////////////////////////////////////////
247
248 // non-inline template implementation (.ct)
249
250 template <class FunctionTraits, class ReturnValue>
251 prefix_ void senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
252 v_execute(std::ostream & os, ParseCommandInfo const & command)
253     const
254 {
255     // We NEED to know the number of arguments beforehand so we can assign default values
256     // correctly ... hrmpf ...
257     unsigned nArgs ( std::distance(command.arguments().begin(), command.arguments().end()) );
258     if ( nArgs > BOOST_PP_ITERATION() )
259         throw SyntaxErrorException("invalid number of arguments");
260     int nDefaults ( BOOST_PP_ITERATION() - nArgs );
261     (void) nDefaults;
262
263     typedef typename boost::range_reverse_iterator<const ParseCommandInfo::ArgumentsRange>::type
264         riterator;
265     riterator i (boost::rbegin(command.arguments()));
266     riterator const i_end (boost::rend(command.arguments()));
267
268 #   define mpp_l(z,n,d)                                                                           \
269         mpp_ArgTypeN(n) mpp_ArgN(n) (arg<n>().defaultValue);                                      \
270         if (! arg(n).hasDefault || nDefaults-- <= 0) {                                            \
271             if (i == i_end)                                                                       \
272                 throw SyntaxErrorException("invalid number of arguments");                        \
273             if (arg<n>().parser)                                                                  \
274                 arg<n>().parser( *(i++), mpp_ArgN(n) );                                           \
275             else                                                                                  \
276                 ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) );                  \
277         }
278 #   define mpp_l_(z,n,d) mpp_l(z, BOOST_PP_SUB(BOOST_PP_DEC(BOOST_PP_ITERATION()), n), d)
279     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l_, _ ) 
280 #   undef mpp_l
281 #   undef mpp_l_
282
283     if (formatter_)
284         formatter_( function_(os mpp_TrailingArgs()), os );
285     else
286         ReturnValueTraits<result_type>::format( function_(os mpp_TrailingArgs()), os );
287     os << "\n";
288 }
289
290 template <class FunctionTraits>
291 prefix_ void senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
292 v_execute(std::ostream & os, ParseCommandInfo const & command)
293     const
294 {
295     // We NEED to know the number of arguments beforehand so we can assign default values
296     // correctly ... hrmpf ...
297     unsigned nArgs ( std::distance(command.arguments().begin(), command.arguments().end()) );
298     if ( nArgs > BOOST_PP_ITERATION() )
299         throw SyntaxErrorException("invalid number of arguments");
300     int nDefaults ( BOOST_PP_ITERATION() - nArgs );
301     (void) nDefaults;
302
303     typedef typename boost::range_reverse_iterator<const ParseCommandInfo::ArgumentsRange>::type
304         riterator;
305     riterator i (boost::rbegin(command.arguments()));
306     riterator const i_end (boost::rend(command.arguments()));
307
308 #   define mpp_l(z,n,d)                                                                           \
309         mpp_ArgTypeN(n) mpp_ArgN(n) (arg<n>().defaultValue);                                      \
310         if (! arg(n).hasDefault || nDefaults-- <= 0) {                                            \
311             if (i == i_end)                                                                       \
312                 throw SyntaxErrorException("invalid number of arguments");                        \
313             if (arg<n>().parser)                                                                  \
314                 arg<n>().parser( *(i++), mpp_ArgN(n) );                                           \
315             else                                                                                  \
316                 ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) );                  \
317         }
318 #   define mpp_l_(z,n,d) mpp_l(z, BOOST_PP_SUB(BOOST_PP_DEC(BOOST_PP_ITERATION()), n), d)
319     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l_, _ ) 
320 #   undef mpp_l
321 #   undef mpp_l_
322
323     function_(os mpp_TrailingArgs());
324 }
325
326 // ////////////////////////////////////////////////////////////////////////
327 #elif BOOST_PP_ITERATION_FLAGS()==4 // ////////////////////////////////////
328 // ////////////////////////////////////////////////////////////////////////
329
330 // CreateParsedCommandOverload
331
332 template <class Traits>
333 struct CreateParsedCommandOverload<Traits, true, BOOST_PP_ITERATION()>
334 {
335     typedef typename Traits::traits traits;
336
337     template <class Function>
338     static typename senf::console::ParsedCommandOverload<traits>::ptr create(Function fn)
339         {
340             return senf::console::ParsedCommandOverload<traits>::create(
341                 boost::bind(fn  mpp_TrailingBindArgs()) );
342         }
343
344 };
345
346 // ////////////////////////////////////////////////////////////////////////
347 #elif BOOST_PP_ITERATION_FLAGS()==5 // ////////////////////////////////////
348 // ////////////////////////////////////////////////////////////////////////
349
350 // Create keyword arg forwarding functions
351
352 template <BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), class A ) > 
353 next_type arg ( BOOST_PP_ENUM_BINARY_PARAMS( BOOST_PP_ITERATION(), A, const & a ),
354                 typename arg_params::match< BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), A ) >::type
355                     kw = arg_params()) const {
356     return argInfo( kw(BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), a )) );
357 }
358
359 // ////////////////////////////////////////////////////////////////////////
360 #endif // /////////////////////////////////////////////////////////////////
361 // ////////////////////////////////////////////////////////////////////////
362 // Undefine local Macros
363
364 #undef mpp_TrailingBindArgs
365 #undef mpp_BindArgs_
366
367 #undef mpp_TrailingArgs
368 #undef mpp_Args_
369
370 #undef mpp_ArgTypes
371 #undef mpp_ArgTypes_
372
373 #undef mpp_TrailingArgTypes
374 #undef mpp_TrailingArgTypes_
375
376 #undef mpp_ArgN
377 #undef mpp_ArgTypeN
378
379 // ////////////////////////////////////////////////////////////////////////
380 #endif // /////////////////////////////////////////////////////////////////
381 // ///////////////////////////mpp.e////////////////////////////////////////
382
383 \f
384 // Local Variables:
385 // mode: c++
386 // fill-column: 100
387 // comment-column: 40
388 // c-file-style: "senf"
389 // indent-tabs-mode: nil
390 // ispell-local-dictionary: "american"
391 // compile-command: "scons -u test"
392 // End: