57948c1972da882599f521d47abd5256c1d134e6
[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/cat.hpp>
33 #include <boost/preprocessor/arithmetic/inc.hpp>
34 #include <boost/preprocessor/repetition/repeat.hpp>
35 #include <boost/type_traits/remove_reference.hpp>
36 #include <boost/type_traits/remove_const.hpp>
37 #include <boost/bind.hpp>
38
39 // ///////////////////////////mpp.p////////////////////////////////////////
40 #elif BOOST_PP_IS_ITERATING // ////////////////////////////////////////////
41 // ////////////////////////////////////////////////////////////////////////
42 // Local Macros
43
44 #define mpp_ArgTypeN(n) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(n)), _type)
45 #define mpp_ArgN(n) BOOST_PP_CAT(arg, BOOST_PP_INC(n))
46
47 #define mpp_ArgTypes_(z,n,d) typename traits::mpp_ArgTypeN(n)
48 #define mpp_TrailingArgTypes() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_ArgTypes_, _ )
49
50 #define mpp_Args_(z,n,d) boost::cref(mpp_ArgN(n))
51 #define mpp_TrailingArgs() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_Args_, _ )
52
53 #define mpp_BindArgs_(z,n,d) BOOST_PP_CAT( _, BOOST_PP_INC(BOOST_PP_INC(n)))
54 #define mpp_TrailingBindArgs() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_BindArgs_, _ )
55
56 // ////////////////////////////////////////////////////////////////////////
57 #if BOOST_PP_ITERATION_FLAGS()==1 // //////////////////////////////////////
58 // ////////////////////////////////////////////////////////////////////////
59
60 // Header file (.hh)
61
62 template <class FunctionTraits>
63 class ParsedCommandOverload<FunctionTraits, BOOST_PP_ITERATION() >
64     : public ParsedCommandOverloadBase
65 {
66 public:
67     typedef boost::intrusive_ptr<ParsedCommandOverload> ptr;
68     typedef FunctionTraits traits;
69     typedef boost::function<typename traits::result_type(std::ostream &
70                                                          mpp_TrailingArgTypes())> Function;
71
72 #   define mpp_l(z,n,d)                                                                           \
73         typedef typename boost::remove_const<                                                     \
74             typename boost::remove_reference< typename traits::mpp_ArgTypeN(n) >::type >::type    \
75                 mpp_ArgTypeN(n);
76     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
77 #   undef mpp_l
78
79     static ptr create(Function fn);
80
81 protected:
82
83 private:
84     ParsedCommandOverload(Function fn);
85
86     virtual void v_execute(std::ostream & os, ParseCommandInfo const & command) const;
87
88     Function function_;
89 };
90
91 // ////////////////////////////////////////////////////////////////////////
92 #elif BOOST_PP_ITERATION_FLAGS()==2 // ////////////////////////////////////
93 // ////////////////////////////////////////////////////////////////////////
94
95 // inline template implementation (.cti)
96
97 template <class FunctionTraits>
98 prefix_ typename senf::console::ParsedCommandOverload<FunctionTraits, BOOST_PP_ITERATION() >::ptr
99 senf::console::ParsedCommandOverload<FunctionTraits, BOOST_PP_ITERATION() >::create(Function fn)
100 {
101     return ptr(new ParsedCommandOverload(fn));
102 }
103
104 template <class FunctionTraits>
105 prefix_
106 senf::console::ParsedCommandOverload<FunctionTraits,BOOST_PP_ITERATION()>::
107 ParsedCommandOverload(Function fn)
108     : function_ (fn) 
109 {
110 #   define mpp_l(z,n,d) addParameter< mpp_ArgTypeN(n) >();
111     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
112 #   undef mpp_l
113 }
114
115 // ////////////////////////////////////////////////////////////////////////
116 #elif BOOST_PP_ITERATION_FLAGS()==3 // ////////////////////////////////////
117 // ////////////////////////////////////////////////////////////////////////
118
119 // non-inline template implementation (.ct)
120
121 template <class FunctionTraits>
122 prefix_ void senf::console::ParsedCommandOverload<FunctionTraits, BOOST_PP_ITERATION() >::
123 v_execute(std::ostream & os, ParseCommandInfo const & command)
124     const
125 {
126     if ( command.arguments().size() > BOOST_PP_ITERATION()
127          || (command.arguments().size() < BOOST_PP_ITERATION()
128              && ! arg( BOOST_PP_ITERATION()-1 ).hasDefault) )
129         throw SyntaxErrorException("invalid number of arguments");
130
131     // First define local variables argN for the parameters. The variables are initialized to their
132     // default values
133 #   define mpp_l(z,n,d) mpp_ArgTypeN(n) mpp_ArgN(n) (arg< mpp_ArgTypeN(n) >( n ).defaultValue);
134     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ ) 
135 #   undef mpp_l
136     
137     ParseCommandInfo::argument_iterator i (command.arguments().begin());
138     ParseCommandInfo::argument_iterator const i_end (command.arguments().end());
139
140     // Now parse the arguments which are provided leaving the trailing arguments at their default
141     // value. We have already checked above, whether those default values are valid. Be aware, that
142     // the following cases do NOT have 'break' statements !
143
144     switch (BOOST_PP_ITERATION() - command.arguments().size()) {
145
146 #   define mpp_l(z,n,d)                                                                           \
147         case n :                                                                                  \
148             detail::ParameterTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) );
149     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ ) 
150 #   undef mpp_l
151
152     default : // This happens, if ALL arguments are defaulted
153         ;
154     }
155
156     // Now call the function binding the arguments to the values parsed above. callAndWrite is
157     // specialized to ignore a 'void' return value but automatically write all other values to the
158     // output stream.
159     detail::ReturnValueTraits<typename traits::result_type>::callAndWrite(
160         boost::bind(function_, boost::ref(os)
161                     mpp_TrailingArgs()),
162         os );
163 }
164
165 // ////////////////////////////////////////////////////////////////////////
166 #elif BOOST_PP_ITERATION_FLAGS()==4 // ////////////////////////////////////
167 // ////////////////////////////////////////////////////////////////////////
168
169 // CreateParsedCommandOverload
170
171 template <class Traits>
172 struct CreateParsedCommandOverload<Traits, true, BOOST_PP_ITERATION()>
173 {
174     typedef Traits traits;
175
176     template <class Function>
177     static typename senf::console::ParsedCommandOverload<traits>::ptr create(Function fn)
178         {
179             return senf::console::ParsedCommandOverload<traits>::create(
180                 boost::bind(fn  mpp_TrailingBindArgs()) );
181         }
182
183 };
184
185 // ////////////////////////////////////////////////////////////////////////
186 #endif // /////////////////////////////////////////////////////////////////
187 // ////////////////////////////////////////////////////////////////////////
188 // Undefine local Macros
189
190 #undef mpp_TrailingArgs
191 #undef mpp_Args_
192
193 #undef mpp_TrailingArgTypes
194 #undef mpp_ArgTypes_
195
196 #undef mpp_ArgN
197 #undef mpp_ArgTypeN
198
199 // ////////////////////////////////////////////////////////////////////////
200 #endif // /////////////////////////////////////////////////////////////////
201 // ///////////////////////////mpp.e////////////////////////////////////////
202
203 \f
204 // Local Variables:
205 // mode: c++
206 // fill-column: 100
207 // comment-column: 40
208 // c-file-style: "senf"
209 // indent-tabs-mode: nil
210 // ispell-local-dictionary: "american"
211 // compile-command: "scons -u test"
212 // End: