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