d8a9468019d83344b0bf1d455a4d6bc85766d342
[senf.git] / Scheduler / Console / Variables.hh
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 Variables public header */
25
26 #ifndef HH_Variables_
27 #define HH_Variables_ 1
28
29 // Custom includes
30 #include <boost/utility.hpp>
31 #include <boost/type_traits/is_convertible.hpp>
32 #include <boost/ref.hpp>
33 #include "ParsedCommand.hh"
34
35 #include "Variables.ih"
36 //#include "Variables.mpp"
37 ///////////////////////////////hh.p////////////////////////////////////////
38
39 namespace senf {
40 namespace console {
41
42     class ScopedDirectoryBase;
43     template <class Variable> class VariableAttributor;
44
45 #ifndef DOXYGEN
46
47     template <class Variable>
48     VariableAttributor<Variable> senf_console_add_node(
49         DirectoryNode & node, std::string const & name, Variable & var, int,
50         typename boost::disable_if< boost::is_convertible<Variable*, ScopedDirectoryBase*> >::type * = 0,
51         typename boost::disable_if_c<detail::ParsedCommandTraits<Variable>::is_callable>::type * = 0);
52
53     template <class Variable>
54     typename detail::VariableNodeCreator<Variable>::result_type
55     senf_console_add_node(DirectoryNode & node, std::string const & name, 
56                           boost::reference_wrapper<Variable> var, int);
57
58     template <class Variable, class Owner>
59     VariableAttributor<Variable> senf_console_add_node(
60         DirectoryNode & node, Owner & owner, std::string const & name, Variable & var, int,
61         typename boost::disable_if< boost::is_convertible<Variable*, ScopedDirectoryBase*> >::type * = 0,
62         typename boost::disable_if_c<detail::ParsedCommandTraits<Variable>::is_callable>::type * = 0);
63
64     template <class Variable, class Owner>
65     typename detail::VariableNodeCreator<Variable>::result_type
66     senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name, 
67                           boost::reference_wrapper<Variable> var, int);
68
69 #endif
70
71     /** \brief Variable command attributes (const)
72         
73         \see VariableAttributor
74      */
75     template <class Variable>
76     class ConstVariableAttributor
77     {
78     public:
79         typedef typename detail::QueryVariable<Variable>::Traits::Overload QueryOverload;
80         typedef typename QueryOverload::Formatter Formatter;
81         typedef OverloadedCommandNode node_type;
82         typedef ConstVariableAttributor return_type;
83
84         ConstVariableAttributor doc(std::string const & doc);
85         ConstVariableAttributor formatter(Formatter formatter);
86
87     protected:
88         explicit ConstVariableAttributor(QueryOverload & queryOverload);
89
90     private:
91         QueryOverload & queryOverload_;
92
93         friend class detail::VariableNodeCreator<Variable const>;
94     };
95  
96     /** \brief Variable command attributes
97
98         Variable commands allow to register any arbitrary variable as a command node. The variable
99         will be registered as two command overloads: One which takes a single argument of the
100         variables type to set the variable and another one taking no arguments and just querying the
101         current variable value.
102         \code
103         int var;
104         ScopedDirectory<> dir;
105
106         dir.add("var", var);
107         \endcode
108
109         Variables should be registered only with a ScopedDirectory declared in the same scope
110         (e.g. as a class member for member variables). This ensures, that the variable node is
111         removed from the tree when the scope is destroyed.
112
113         Since a variable command is added as a combination of two ordinary overloads, it is possible
114         to register additional overloads with the same name before or after registering the
115         variable. 
116
117         It is also possible, to register a variable read-only. To achieve this, just wrap it with \c
118         boost::cref(). Such a variable cannot be changed only queried. Therefore, it does not have
119         the parser() and typeName() attributes.
120         \code
121         dir.add("const_var", boost::cref(var))
122         \endcode
123
124         \ingroup console_commands
125      */
126    template <class Variable>
127     class VariableAttributor
128         : public ConstVariableAttributor<Variable>
129     {
130     public:
131         typedef typename detail::SetVariable<Variable>::Traits::Overload SetOverload;
132         typedef typename detail::ArgumentInfo<typename SetOverload::arg1_type>::Parser Parser;
133         typedef typename detail::SetVariable<Variable>::OnChangeHandler OnChangeHandler;
134         typedef OverloadedCommandNode node_type;
135         typedef VariableAttributor return_type;
136
137         typedef typename ConstVariableAttributor<Variable>::Formatter Formatter;
138         typedef typename ConstVariableAttributor<Variable>::QueryOverload QueryOverload;
139
140         VariableAttributor doc(std::string const & doc); ///< Set documentation of the variable
141         VariableAttributor formatter(Formatter formatter); ///< Set formatter
142                                         /**< The \a formatter must be a callable with a signature
143                                              compatible with
144                                              \code
145                                              void formatter(Variable const & value, std::ostream & os);
146                                              \endcode
147                                              The \a formatter takes the return value of the call \a
148                                              value and writes it properly formated to \a os. */
149        
150         VariableAttributor parser(Parser parser); ///< Set argument parser
151                                         /**< The parser is an arbitrary callable object with
152                                              the signature
153                                              \code
154                                                  void parser(senf::console::ParseCommandInfo::TokensRange const & tokens, value_type & out);
155                                              \endcode
156
157                                              where \c value_type is the type of the overload
158                                              parameter. The parser must read and parse the complete
159                                              \a tokens range and return the parsed value in \a
160                                              out. If the parser fails, it must raise a
161                                              senf::console::SyntaxErrorException. */
162         VariableAttributor typeName(std::string const & name); ///< Set name of the variable type
163         VariableAttributor onChange(OnChangeHandler handler); ///< Set change callback
164                                         /**< The \a handler callback is called, whenever the value
165                                              of the variable is changed. The new value has already
166                                              been set, when the callback is called, the old value is
167                                              passed to the callback. The callback must have a
168                                              signature compatible to
169                                              \code
170                                              void handler(Variable const & oldValue);
171                                              \endcode */
172  
173     protected:
174
175     private:
176         VariableAttributor(QueryOverload & queryOverload, SetOverload & setOverload, 
177                            Variable & var);
178
179         SetOverload & setOverload_;
180         Variable & var_;
181
182         friend class detail::VariableNodeCreator<Variable>;
183     };
184 }}
185
186 ///////////////////////////////hh.e////////////////////////////////////////
187 //#include "Variables.cci"
188 //#include "Variables.ct"
189 #include "Variables.cti"
190 #endif
191
192 \f
193 // Local Variables:
194 // mode: c++
195 // fill-column: 100
196 // comment-column: 40
197 // c-file-style: "senf"
198 // indent-tabs-mode: nil
199 // ispell-local-dictionary: "american"
200 // compile-command: "scons -u test"
201 // End: