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