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