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