ee78fbce7d29312f8d1c8173c511ad4c64323d9f
[senf.git] / senf / Utils / 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_SENF_Scheduler_Console_Variables_
27 #define HH_SENF_Scheduler_Console_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 "Node.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 namespace factory {
46
47 #ifndef DOXYGEN
48
49     template <class Variable>
50     class ConstVariableFactory
51         : public detail::NodeFactory
52     {
53     public:
54         typedef typename detail::QueryVariable<Variable>::Traits::Overload QueryOverload;
55         typedef typename QueryOverload::Formatter Formatter;
56         typedef OverloadedCommandNode node_type;
57         typedef OverloadedCommandNode & result_type;
58
59         ConstVariableFactory doc(std::string const & doc);
60         ConstVariableFactory shortdoc(std::string const & doc);
61         ConstVariableFactory formatter(Formatter formatter);
62
63         OverloadedCommandNode & create(DirectoryNode & dir, std::string const & name) const;
64
65         explicit ConstVariableFactory(Variable const & var);
66
67     private:
68         typename QueryOverload::ptr queryOverload_;
69         boost::optional<std::string> doc_;
70         boost::optional<std::string> shortdoc_;
71     };
72
73 #endif
74
75     /** \brief Variable node factory
76
77         Variable commands allow to register any arbitrary variable as a command node. The variable
78         will be registered as two command overloads: One which takes a single argument of the
79         variables type to set the variable and another one taking no arguments and just querying the
80         current variable value.
81         \code
82             int var;
83             ScopedDirectory<> dir;
84
85         dir.add("var", fty::Variable(var));
86         \endcode
87
88         Variables should be registered only with a ScopedDirectory declared in the same scope
89         (e.g. as a class member for member variables). This ensures, that the variable node is
90         removed from the tree when the scope is destroyed.
91
92         Since a variable command is added as a combination of two ordinary overloads, it is possible
93         to register additional overloads with the same name before or after registering the
94         variable.
95
96         It is also possible, to register a variable read-only. To achieve this, just wrap it with \c
97         boost::cref(). Such a variable only queried. Therefore, it does not have the parser() and
98         typeName() attributes.
99         \code
100             dir.add("const_var", fty::Variable(boost::cref(var)));
101         \endcode
102
103         \note Even though the interface is documented as a class, in reality it is implemented using
104             factory functions returning instances of an internal factory class.
105
106         \see \ref console_variables
107      */
108 #ifdef DOXYGEN
109     class Variable
110 #else
111     template <class Variable>
112     class VariableFactory
113         : public ConstVariableFactory<Variable>
114 #endif
115     {
116     public:
117         typedef typename detail::SetVariable<Variable>::Traits::Overload SetOverload;
118         typedef typename detail::ArgumentInfo<typename SetOverload::arg1_type>::Parser Parser;
119         typedef typename detail::SetVariable<Variable>::OnChangeHandler OnChangeHandler;
120
121         typedef typename ConstVariableFactory<Variable>::Formatter Formatter;
122         typedef typename ConstVariableFactory<Variable>::QueryOverload QueryOverload;
123
124         VariableFactory doc(std::string const & doc); ///< Set documentation of the variable
125         VariableFactory shortdoc(std::string const & doc); ///< Set short documentation
126         VariableFactory formatter(Formatter formatter); ///< Set formatter
127                                         /**< The \a formatter must be a callable with a signature
128                                              compatible with
129                                              \code
130                                                  void formatter(Variable const & value, std::ostream & os);
131                                              \endcode
132                                                  The \a formatter takes the return value of the call \a
133                                                  value and writes it properly formated to \a os. */
134         VariableFactory 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         VariableFactory typeName(std::string const & name); ///< Set name of the variable type
147         VariableFactory 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         explicit VariableFactory(Variable & var); ///< Create Variable node
158
159     protected:
160
161     private:
162         OverloadedCommandNode & create(DirectoryNode & dir, std::string const & name) const;
163
164         typename SetOverload::ptr setOverload_;
165         Variable & var_;
166
167         friend class senf::console::DirectoryNode;
168     };
169
170 #ifndef DOXYGEN
171
172     template <class Var>
173     VariableFactory<Var> Variable(Var & var);
174
175     template <class Var>
176     VariableFactory<Var> Variable(boost::reference_wrapper<Var> var);
177
178     template <class Var>
179     ConstVariableFactory<Var> Variable(Var const & var);
180
181     template <class Var>
182     ConstVariableFactory<Var> Variable(boost::reference_wrapper<Var const> var);
183
184 #endif
185
186 }}}
187
188 ///////////////////////////////hh.e////////////////////////////////////////
189 //#include "Variables.cci"
190 //#include "Variables.ct"
191 #include "Variables.cti"
192 #endif
193
194 \f
195 // Local Variables:
196 // mode: c++
197 // fill-column: 100
198 // comment-column: 40
199 // c-file-style: "senf"
200 // indent-tabs-mode: nil
201 // ispell-local-dictionary: "american"
202 // compile-command: "scons -u test"
203 // End: