switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Utils / Console / ParsedCommand.ih
1 // $Id$
2 //
3 // Copyright (C) 2008
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief ParsedCommand internal header */
30
31 #ifndef IH_SENF_Scheduler_Console_ParsedCommand_
32 #define IH_SENF_Scheduler_Console_ParsedCommand_ 1
33
34 // Custom includes
35 #include <boost/function.hpp>
36 #include <boost/intrusive_ptr.hpp>
37 #include "Parse.hh"
38
39 //-/////////////////////////////////////////////////////////////////////////////////////////////////
40
41 namespace senf {
42 namespace console {
43
44     template < class FunctionTraits,
45                class ReturnType=typename FunctionTraits::result_type,
46                unsigned arity=FunctionTraits::arity >
47     class ParsedCommandOverload;
48
49     template < class Overload,
50                unsigned index=0,
51                bool flag=(index < unsigned(Overload::traits::arity)) >
52     class ParsedArgumentAttributor;
53
54 namespace detail {
55
56     /** \brief Internal: Argument information structure
57
58         This class is used to hold argument information for automatically parsed commands.
59
60         \see ParsedCommandOverloadBase
61      */
62     struct ArgumentInfoBase
63         : public intrusive_refcount
64     {
65         typedef boost::intrusive_ptr<ArgumentInfoBase> ptr;
66
67         std::string type;
68         std::string name;
69         std::string defaultDoc;
70         bool hasDefault;
71         std::string doc;
72         bool singleToken;
73
74         explicit ArgumentInfoBase(std::string const & type, bool singleToken=false);
75         virtual ~ArgumentInfoBase();
76
77         virtual std::string defaultValueStr() const = 0;
78     };
79
80     /** \brief Internal: Argument information structure
81
82         This class is used to hold argument information for automatically parsed commands.
83
84         \see ParsedCommandOverloadBase
85      */
86     template <class ParameterType>
87     struct ArgumentInfo
88         : public ArgumentInfoBase
89     {
90         typedef boost::intrusive_ptr<ArgumentInfo> ptr;
91         typedef boost::function<void (ParseCommandInfo::TokensRange const &,
92                                       ParameterType &)> Parser;
93
94         static ptr create();
95         ArgumentInfo();
96
97         ParameterType defaultValue;
98         Parser parser;
99
100         virtual std::string defaultValueStr() const;
101     };
102
103 #ifndef DOXYGEN
104
105     // FirstArgType returns void, if the function has no arguments, otherwise it returns arg1_type
106
107     template <class Traits, bool flag=(Traits::arity>0)>
108     struct FirstArgType
109     {
110         typedef void type;
111     };
112
113     template <class Traits>
114     struct FirstArgType<Traits,true>
115     {
116         typedef typename Traits::arg1_type type;
117     };
118
119     template <class FnunctionP, class Function, bool isFN=boost::is_function<Function>::value>
120     struct ParsedCommandTraits_i
121     {
122         static const bool is_callable = false;
123         static const bool is_member = false;
124         static const bool is_simple = false;
125     };
126
127     template <class FunctionP, class Function>
128     struct ParsedCommandTraits_i<FunctionP, Function, true>
129     {
130         typedef FunctionP base_type;
131         typedef typename senf::remove_any_pointer<base_type>::type function_type;
132         typedef boost::function_traits<function_type> base_traits;
133         typedef typename FirstArgType<base_traits>::type first_arg_type;
134
135         static const bool has_ostream_arg = boost::is_same<first_arg_type, std::ostream &>::value;
136
137         typedef typename boost::mpl::if_c<
138             has_ostream_arg,
139             typename function_traits_remove_arg<base_traits>::type,
140             base_traits>
141         ::type traits;
142
143         typedef typename senf::remove_cvref<typename base_traits::result_type>::type result_type;
144
145         static const bool is_callable = true;
146         static const bool is_member = boost::is_member_pointer<base_type>::value;
147         static const bool is_simple = false;
148
149         typedef typename senf::member_class<base_type>::type class_type;
150
151         typedef ParsedCommandOverload<traits> Overload;
152         typedef ParsedArgumentAttributor<Overload> Attributor;
153     };
154
155     // Disable auto-parsing for ParseCommandInfo arg -> register manually parsed command
156     template <class FunctionP>
157     struct ParsedCommandTraits_i<FunctionP, void (std::ostream &, ParseCommandInfo const &), true>
158     {
159         static const bool is_simple = true;
160     };
161
162     template <class FunctionP>
163     struct ParsedCommandTraits
164         : public ParsedCommandTraits_i< FunctionP,
165                                         typename senf::remove_any_pointer<FunctionP>::type >
166     {};
167
168     struct ParsedCommandAddNodeAccess;
169
170     // What is THIS about ??
171
172     // Ok, here's the dope: parsed commands may optionally have an std::ostream & first argument. If
173     // this argument is given, then the function will be called with the console output stream as
174     // it's first argument.
175     //
176     // This is implemented in the following way: ParsedCommandOverload (the class responsible for
177     // calling the callback) will ALWAYS pass the stream as first argument. If the user callback
178     // expects os as it's first argument, 'ignoreOneArg' will be false and the user supplied
179     // function will be directly passed to ParsedCommandOverload.
180     //
181     // If however, it does NOT take an std::ostream first argument, 'ignoreOneArg' will be true and
182     // the create member will use boost::bind to DROP the first argument.
183
184     template <class Traits,
185               bool ignoreOneArg=! Traits::has_ostream_arg,
186               unsigned arity=Traits::traits::arity>
187     struct CreateParsedCommandOverload
188     {};
189
190     template <class Traits, unsigned arity>
191     struct CreateParsedCommandOverload<Traits, false, arity>
192     {
193         typedef typename Traits::traits traits;
194
195         template <class Function>
196         static typename senf::console::ParsedCommandOverload<traits>::ptr create(Function fn)
197             { return senf::console::ParsedCommandOverload<traits>::create(fn); };
198     };
199
200 #   define BOOST_PP_ITERATION_PARAMS_1 (4, (0, SENF_CONSOLE_MAX_COMMAND_ARITY,                     \
201                                             SENF_ABSOLUTE_INCLUDE_PATH(Utils/Console/ParsedCommand.mpp), \
202                                             4))
203 #   include BOOST_PP_ITERATE()
204
205 #endif
206
207 }}}
208
209 //-/////////////////////////////////////////////////////////////////////////////////////////////////
210 #endif
211
212 \f
213 // Local Variables:
214 // mode: c++
215 // fill-column: 100
216 // comment-column: 40
217 // c-file-style: "senf"
218 // indent-tabs-mode: nil
219 // ispell-local-dictionary: "american"
220 // compile-command: "scons -u test"
221 // End: