72f372ee91568081637551c35f482272fa3519ba
[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 template <class ArgumentPack>
122 prefix_ typename senf::console::ParsedAttributeAttributor<Overload,index,flag>::next_type
123 senf::console::ParsedAttributeAttributor<Overload,index,flag>::
124 argInfo(ArgumentPack const & args)
125     const
126 {
127     typedef typename boost::parameter::binding<
128         ArgumentPack, tag::detail::default_value_>::type default_value_t;
129     return argInfo( args, boost::is_same<default_value_t, void>() );
130 }
131
132 template <class Overload, unsigned index, bool flag>
133 template <class ArgumentPack>
134 prefix_ typename senf::console::ParsedAttributeAttributor<Overload,index,flag>::next_type
135 senf::console::ParsedAttributeAttributor<Overload,index,flag>::
136 argInfo(ArgumentPack const & args, boost::mpl::true_)
137     const
138 {
139     return argInfo( args[tag::name_ | ""], 
140                     args[tag::description_ | ""] );
141
142 }
143
144 template <class Overload, unsigned index, bool flag>
145 template <class ArgumentPack>
146 prefix_ typename senf::console::ParsedAttributeAttributor<Overload,index,flag>::next_type
147 senf::console::ParsedAttributeAttributor<Overload,index,flag>::
148 argInfo(ArgumentPack const & args, boost::mpl::false_)
149     const
150 {
151     return argInfo( args[tag::name_ | ""], 
152                     args[tag::description_ | ""], 
153                     args[tag::default_value_ | value_type()] );
154 }
155
156 template <class Overload, unsigned index, bool flag>
157 prefix_ typename senf::console::ParsedAttributeAttributor<Overload,index,flag>::next_type
158 senf::console::ParsedAttributeAttributor<Overload,index,flag>::argInfo(std::string const & name,
159                                                                        std::string const & doc)
160     const
161 {
162     this->argName(name);
163     this->argDoc(doc);
164     return next();
165 }
166
167 template <class Overload, unsigned index, bool flag>
168 prefix_ typename senf::console::ParsedAttributeAttributor<Overload,index,flag>::next_type
169 senf::console::ParsedAttributeAttributor<Overload,index,flag>::argInfo(std::string const & name,
170                                                                        std::string const & doc,
171                                                                        value_type const & value)
172     const
173 {
174     this->argName(name);
175     this->argDoc(doc);
176     defaultValue(value);
177     return next();
178 }
179
180 template <class Overload, unsigned index, bool flag>
181 prefix_
182 senf::console::ParsedAttributeAttributor<Overload,index,flag>::
183 ParsedAttributeAttributor(Overload & overload)
184     : ParsedAttributeAttributorBase<Overload, ParsedAttributeAttributor> (overload, index)
185 {}
186
187 template <class Overload, unsigned index, bool flag>
188 prefix_ senf::console::ParsedAttributeAttributor<Overload, index+1>
189 senf::console::ParsedAttributeAttributor<Overload,index,flag>::next()
190     const
191 {
192     return ParsedAttributeAttributor<Overload, index+1>(this->overload());
193 }
194
195 template <class Overload, unsigned index, bool flag>
196 prefix_ void senf::console::ParsedAttributeAttributor<Overload,index,flag>::
197 defaultValue(value_type const & value)
198     const
199 {
200     ParsedCommandAttributorBase::defaultValue<arg_type>(value);
201 }
202
203 ///////////////////////////////////////////////////////////////////////////
204 // senf::console::ParsedAttributeAttributor<Overload, index, false>
205
206 template <class Overload, unsigned index>
207 prefix_
208 senf::console::ParsedAttributeAttributor<Overload, index, false>::
209 ParsedAttributeAttributor(Overload & overload)
210     : ParsedCommandAttributor<Overload> (overload, index)
211 {}
212
213 ///////////////////////////////////////////////////////////////////////////
214 // namespace members
215
216 namespace {
217
218     // What is THIS about ??
219
220     // Ok, here's the dope: parsed commands may optionally have an std::ostream & first argument. If
221     // this argument is given, then the function will be called with the console output stream as
222     // it's first argument.
223     //
224     // This is implemented in the following way: ParsedCommandOverload (the class responsible for
225     // calling the callback) will ALWAYS pass the stream as first argument. If the user callback
226     // expects os as it's first argument, 'ignoreOneArg' will be false and the user supplied
227     // function will be directly passed to ParsedCommandOverload.
228     //
229     // If however, it does NOT take an std::ostream first argument, 'ignoreOneArg' will be true and
230     // the create member will use boost::bind to DROP the first argument.
231     
232     template <class Traits, bool ignoreOneArg, unsigned arity=Traits::arity>
233     struct CreateParsedCommandOverload
234     {};
235
236     template <class Traits, unsigned arity>
237     struct CreateParsedCommandOverload<Traits, false, arity>
238     {
239         typedef Traits traits;
240         
241         template <class Function>
242         static typename senf::console::ParsedCommandOverload<traits>::ptr create(Function fn) 
243             { return senf::console::ParsedCommandOverload<traits>::create(fn); };
244     };
245
246 #   define BOOST_PP_ITERATION_PARAMS_1 (4, (0, SENF_CONSOLE_MAX_COMMAND_ARITY,                     \
247                                             SENF_ABSOLUTE_INCLUDE_PATH(Console/ParsedCommand.mpp), \
248                                             4))
249 #   include BOOST_PP_ITERATE()
250
251 }
252
253 template <class Function>
254 prefix_ senf::console::ParsedAttributeAttributor<
255     senf::console::ParsedCommandOverload<
256         typename senf::console::detail::ParsedCommandTraits<Function>::traits> >
257 senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name,
258                                      Function fn, int)
259 {
260     OverloadedCommandNode & cmdNode (
261         node.hasChild(name) 
262         ? dynamic_cast<OverloadedCommandNode &>(node(name))
263         : node.add(name, OverloadedCommandNode::create()) );
264
265     typedef detail::ParsedCommandTraits<Function> CmdTraits;
266     typedef ParsedCommandOverload<typename CmdTraits::traits> Overload;
267     typedef ParsedAttributeAttributor<Overload> Attributor;
268
269     return Attributor(
270         cmdNode.add( CreateParsedCommandOverload<
271                          typename CmdTraits::traits, ! CmdTraits::has_ostream_arg>::create(fn) ) );
272 }
273
274 template <class Owner, class Function>
275 prefix_ senf::console::ParsedAttributeAttributor<
276     senf::console::ParsedCommandOverload<
277         typename senf::console::detail::ParsedCommandTraits<Function>::traits> >
278 senf::console::
279 senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
280                       Function fn, int,
281                       typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_member>::type *)
282 {
283     OverloadedCommandNode & cmdNode (
284         node.hasChild(name) 
285         ? dynamic_cast<OverloadedCommandNode &>(node(name))
286         : node.add(name, OverloadedCommandNode::create()) );
287
288     typedef detail::ParsedCommandTraits<Function> CmdTraits;
289     typedef ParsedCommandOverload<typename CmdTraits::traits> Overload;
290     typedef ParsedAttributeAttributor<Overload> Attributor;
291
292     return Attributor(
293         cmdNode.add( CreateParsedCommandOverload<
294                          typename CmdTraits::traits, ! CmdTraits::has_ostream_arg>::create(
295                              senf::membind(fn,&owner)) ) );
296 }
297
298 ///////////////////////////////cti.e///////////////////////////////////////
299 #undef prefix_
300
301 \f
302 // Local Variables:
303 // mode: c++
304 // fill-column: 100
305 // comment-column: 40
306 // c-file-style: "senf"
307 // indent-tabs-mode: nil
308 // ispell-local-dictionary: "american"
309 // compile-command: "scons -u test"
310 // End: