Console: More extensible keyword parameter dispatching in arg() attribute
[senf.git] / Console / ParsedCommand.cti
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 inline template implementation */
25
26 #include "ParsedCommand.ih"
27
28 // Custom includes
29 #include "../Utils/membind.hh"
30 #include <boost/format.hpp>
31 #include <boost/parameter/binding.hpp>
32
33 #define prefix_ inline
34 ///////////////////////////////cti.p///////////////////////////////////////
35
36 ///////////////////////////////////////////////////////////////////////////
37 // senf::console::ParsedCommandOverloadBase
38
39 template <class Type>
40 prefix_ senf::console::detail::ParameterInfo<Type> &
41 senf::console::ParsedCommandOverloadBase::arg(unsigned n)
42     const
43 {
44     return dynamic_cast<detail::ParameterInfo<Type> &>(arg(n));
45 }
46
47 template <class Type>
48 prefix_ void senf::console::ParsedCommandOverloadBase::addParameter()
49 {
50     parameters_.push_back(detail::ParameterInfo<Type>::create());
51 }
52
53 ///////////////////////////////////////////////////////////////////////////
54 // senf::console::ParsedCommandOverload<FunctionTraits,n>
55
56 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, SENF_CONSOLE_MAX_COMMAND_ARITY,                       \
57                                          SENF_ABSOLUTE_INCLUDE_PATH(Console/ParsedCommand.mpp),   \
58                                          2))
59 #include BOOST_PP_ITERATE()
60
61 ///////////////////////////////////////////////////////////////////////////
62 // senf::console::ParsedCommandAttributorBase
63
64 template <class Type>
65 prefix_ void senf::console::ParsedCommandAttributorBase::defaultValue(Type const & value)
66     const
67 {
68     overload().arg<Type>(index_).defaultValue = value;
69     overload().arg(index_).hasDefault = true;
70 }
71
72 ///////////////////////////////////////////////////////////////////////////
73 // senf::console::ParsedCommandAttributor<Overload>
74
75 template <class Overload>
76 prefix_ Overload & senf::console::ParsedCommandAttributor<Overload>::overload()
77     const
78 {
79     return static_cast<Overload &>(ParsedCommandAttributorBase::overload());
80 }
81
82 template <class Overload>
83 prefix_
84 senf::console::ParsedCommandAttributor<Overload>::ParsedCommandAttributor(Overload & overload,
85                                                                           unsigned index)
86     : ParsedCommandAttributorBase (overload, index)
87 {}
88
89 ///////////////////////////////////////////////////////////////////////////
90 // senf::console::ParsedAttributeAttributorBase<Overload,Self>
91
92 template <class Overload, class Self>
93 prefix_ Self
94 senf::console::ParsedAttributeAttributorBase<Overload,Self>::doc(std::string const & doc)
95     const
96 {
97     this->ParsedCommandAttributorBase::nodeDoc(doc);
98     return static_cast<Self const &>(*this);
99 }
100
101 template <class Overload, class Self>
102 prefix_ Self senf::console::ParsedAttributeAttributorBase<Overload,Self>::
103 overloadDoc(std::string const & doc)
104     const
105 {
106     this->ParsedCommandAttributorBase::overloadDoc(doc);
107     return static_cast<Self const &>(*this);
108 }
109
110 template <class Overload, class Self>
111 prefix_
112 senf::console::ParsedAttributeAttributorBase<Overload,Self>::
113 ParsedAttributeAttributorBase(Overload & overload, unsigned index)
114     : ParsedCommandAttributor<Overload> (overload, index)
115 {}
116
117 ///////////////////////////////////////////////////////////////////////////
118 // senf::console::ParsedAttributeAttributor<Overload,index,flag>
119
120 template <class Overload, unsigned index, bool flag>
121 prefix_ typename senf::console::ParsedAttributeAttributor<Overload,index,flag>::next_type
122 senf::console::ParsedAttributeAttributor<Overload,index,flag>::arg()
123     const
124 {
125     return next();
126 }
127
128 template <class Overload, unsigned index, bool flag>
129 template <class ArgumentPack>
130 prefix_ typename senf::console::ParsedAttributeAttributor<Overload,index,flag>::next_type
131 senf::console::ParsedAttributeAttributor<Overload,index,flag>::
132 argInfo(ArgumentPack const & args)
133     const
134 {
135 #   define HaveArg(tag) boost::is_same< \
136         typename boost::parameter::binding<ArgumentPack, tag>::type, void >()
137
138     argInfo( kw::name,          args, HaveArg(kw::type::name)          );
139     argInfo( kw::description,   args, HaveArg(kw::type::description)   );
140     argInfo( kw::default_value, args, HaveArg(kw::type::default_value) );
141
142     return next();
143
144 #   undef HaveArg
145 }
146
147 template <class Overload, unsigned index, bool flag>
148 template <class Kw, class ArgumentPack>
149 prefix_ void senf::console::ParsedAttributeAttributor<Overload,index,flag>::
150 argInfo(Kw const &, ArgumentPack const &, boost::mpl::true_)
151     const
152 {}
153
154 template <class Overload, unsigned index, bool flag>
155 template <class ArgumentPack>
156 prefix_ void senf::console::ParsedAttributeAttributor<Overload,index,flag>::
157 argInfo(boost::parameter::keyword<kw::type::name> const &, ArgumentPack const & args,
158         boost::mpl::false_)
159     const
160 {
161     this->argName(args[kw::name]);
162 }
163
164 template <class Overload, unsigned index, bool flag>
165 template <class ArgumentPack>
166 prefix_ void senf::console::ParsedAttributeAttributor<Overload,index,flag>::
167 argInfo(boost::parameter::keyword<kw::type::description> const &, ArgumentPack const & args,
168         boost::mpl::false_)
169     const
170 {
171     this->argDoc(args[kw::description]);
172 }
173
174 template <class Overload, unsigned index, bool flag>
175 template <class ArgumentPack>
176 prefix_ void senf::console::ParsedAttributeAttributor<Overload,index,flag>::
177 argInfo(boost::parameter::keyword<kw::type::default_value> const &, ArgumentPack const & args,
178         boost::mpl::false_)
179     const
180 {
181     this->defaultValue(args[kw::default_value]);
182 }
183
184 template <class Overload, unsigned index, bool flag>
185 prefix_
186 senf::console::ParsedAttributeAttributor<Overload,index,flag>::
187 ParsedAttributeAttributor(Overload & overload)
188     : ParsedAttributeAttributorBase<Overload, ParsedAttributeAttributor> (overload, index)
189 {}
190
191 template <class Overload, unsigned index, bool flag>
192 prefix_ typename senf::console::ParsedAttributeAttributor<Overload,index,flag>::next_type
193 senf::console::ParsedAttributeAttributor<Overload,index,flag>::next()
194     const
195 {
196     return ParsedAttributeAttributor<Overload, index+1>(this->overload());
197 }
198
199 template <class Overload, unsigned index, bool flag>
200 prefix_ void senf::console::ParsedAttributeAttributor<Overload,index,flag>::
201 defaultValue(value_type const & value)
202     const
203 {
204     ParsedCommandAttributorBase::defaultValue<arg_type>(value);
205 }
206
207 ///////////////////////////////////////////////////////////////////////////
208 // senf::console::ParsedAttributeAttributor<Overload, index, false>
209
210 template <class Overload, unsigned index>
211 prefix_
212 senf::console::ParsedAttributeAttributor<Overload, index, false>::
213 ParsedAttributeAttributor(Overload & overload)
214     : ParsedAttributeAttributorBase< Overload, 
215                                      ParsedAttributeAttributor<Overload, index, false> > (overload, index)
216 {}
217
218 ///////////////////////////////////////////////////////////////////////////
219 // namespace members
220
221 namespace {
222
223     // What is THIS about ??
224
225     // Ok, here's the dope: parsed commands may optionally have an std::ostream & first argument. If
226     // this argument is given, then the function will be called with the console output stream as
227     // it's first argument.
228     //
229     // This is implemented in the following way: ParsedCommandOverload (the class responsible for
230     // calling the callback) will ALWAYS pass the stream as first argument. If the user callback
231     // expects os as it's first argument, 'ignoreOneArg' will be false and the user supplied
232     // function will be directly passed to ParsedCommandOverload.
233     //
234     // If however, it does NOT take an std::ostream first argument, 'ignoreOneArg' will be true and
235     // the create member will use boost::bind to DROP the first argument.
236     
237     template <class Traits, bool ignoreOneArg, unsigned arity=Traits::arity>
238     struct CreateParsedCommandOverload
239     {};
240
241     template <class Traits, unsigned arity>
242     struct CreateParsedCommandOverload<Traits, false, arity>
243     {
244         typedef Traits traits;
245         
246         template <class Function>
247         static typename senf::console::ParsedCommandOverload<traits>::ptr create(Function fn) 
248             { return senf::console::ParsedCommandOverload<traits>::create(fn); };
249     };
250
251 #   define BOOST_PP_ITERATION_PARAMS_1 (4, (0, SENF_CONSOLE_MAX_COMMAND_ARITY,                     \
252                                             SENF_ABSOLUTE_INCLUDE_PATH(Console/ParsedCommand.mpp), \
253                                             4))
254 #   include BOOST_PP_ITERATE()
255
256 }
257
258 template <class Function>
259 prefix_ senf::console::ParsedAttributeAttributor<
260     senf::console::ParsedCommandOverload<
261         typename senf::console::detail::ParsedCommandTraits<Function>::traits> >
262 senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name,
263                                      Function fn, int)
264 {
265     OverloadedCommandNode & cmdNode (
266         node.hasChild(name) 
267         ? dynamic_cast<OverloadedCommandNode &>(node(name))
268         : node.add(name, OverloadedCommandNode::create()) );
269
270     typedef detail::ParsedCommandTraits<Function> CmdTraits;
271     typedef ParsedCommandOverload<typename CmdTraits::traits> Overload;
272     typedef ParsedAttributeAttributor<Overload> Attributor;
273
274     return Attributor(
275         cmdNode.add( CreateParsedCommandOverload<
276                          typename CmdTraits::traits, ! CmdTraits::has_ostream_arg>::create(fn) ) );
277 }
278
279 template <class Owner, class Function>
280 prefix_ senf::console::ParsedAttributeAttributor<
281     senf::console::ParsedCommandOverload<
282         typename senf::console::detail::ParsedCommandTraits<Function>::traits> >
283 senf::console::
284 senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
285                       Function fn, int,
286                       typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_member>::type *)
287 {
288     OverloadedCommandNode & cmdNode (
289         node.hasChild(name) 
290         ? dynamic_cast<OverloadedCommandNode &>(node(name))
291         : node.add(name, OverloadedCommandNode::create()) );
292
293     typedef detail::ParsedCommandTraits<Function> CmdTraits;
294     typedef ParsedCommandOverload<typename CmdTraits::traits> Overload;
295     typedef ParsedAttributeAttributor<Overload> Attributor;
296
297     return Attributor(
298         cmdNode.add( CreateParsedCommandOverload<
299                          typename CmdTraits::traits, ! CmdTraits::has_ostream_arg>::create(
300                              senf::membind(fn,&owner)) ) );
301 }
302
303 ///////////////////////////////cti.e///////////////////////////////////////
304 #undef prefix_
305
306 \f
307 // Local Variables:
308 // mode: c++
309 // fill-column: 100
310 // comment-column: 40
311 // c-file-style: "senf"
312 // indent-tabs-mode: nil
313 // ispell-local-dictionary: "american"
314 // compile-command: "scons -u test"
315 // End: