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