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