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