/** \file
\brief Node public header */
-/** \defgroup node_tree The console/config file-system node tree
+/** \defgroup node_tree The node tree
The console/config node tree is the central data-structure of the library. Into this tree, all
commands and parameters are entered. The tree is then exposed using a file-system like
\li An arbitrary node can be created and then (possibly later) added to the tree using the
corresponding senf::console::DirectoryNode::add() overload.
\li A senf::console::CommandNode is normally added to the tree by directly adding a callback
- using one of the overloaded senf::console::DirectoryNode::add() members.
+ using one of the overloaded senf::console::DirectoryNode::add() members. See \ref
+ console_commands.
When directly adding a node callback, the type of node added depends on the type of
callback. The callback types which can be added are listed at \ref console_callbacks.
#include "../Utils/Exception.hh"
#include "../Utils/mpl.hh"
#include "../Utils/Logger/SenfLog.hh"
+#include "../Utils/type_traits.hh"
#include "Parse.hh"
//#include "Node.mpp"
///////////////////////////////hh.p////////////////////////////////////////
-#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
-
namespace senf {
namespace console {
+ class LinkNode;
class DirectoryNode;
class CommandNode;
+ DirectoryNode & root();
+
/** \brief Config/console node tree base-class
GenericNode is the base class of all node objects. There are two basic node types derived
std::string path() const; ///< Node path
/**< The node path is built by joining the names of all
parent nodes with '/' chars. */
+ std::string path(DirectoryNode const & root) const;
+ ///< Node path up to \a root
+ /**< The node path is built by joining the names of all
+ parent nodes up to \a root with '/' chars. */
ptr unlink(); ///< Remove node from it's parent directory
/**< You may either discard the return value and thereby
ptr thisptr(); ///< Get smart pointer to node
cptr thisptr() const; ///< Get smart pointer to node (const)
+ bool isChildOf(DirectoryNode & parent) const;
+ ///< \c true, if node is a child of \a parent
+ /**< Will also return \c true, if \a parent is the current
+ node. */
+
+ bool operator== (GenericNode & other) const;
+ /// \c true, if this and \a other are the same node
+ bool operator!= (GenericNode & other) const;
+ /// \c true, if this and \a other are different nodes
+
+ bool isDirectory() const; ///< \c true, if this is a drectory node
+ bool isLink() const; ///< \c true, if this is a link node
+ bool isCommand() const; ///< \c true, if this is a command node
+
protected:
GenericNode();
friend class DirectoryNode;
};
+ /** \brief Config/console tree link node
+
+ A LinkNode references another node and provides an additional alias name for that node. A
+ LinkNode works like a mixture of UNIX symlinks and hardlinks: It is an explicit link like a
+ UNIX symlink but references another node directly (not via it's path) like a UNIX
+ hardlink. Therefore, a LinkNode works across chroot().
+ */
+ class LinkNode
+ : public GenericNode
+ {
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ // Types
+
+ typedef boost::shared_ptr<LinkNode> ptr;
+ typedef boost::shared_ptr<LinkNode const> cptr;
+ typedef boost::weak_ptr<LinkNode> weak_ptr;
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///\name Structors and default members
+ ///@{
+
+ static ptr create(GenericNode & node); ///< Create new link node.
+ /**< You should normally use DirectoryNode::link() to
+ create a link node. */
+
+ ///@}
+ ///////////////////////////////////////////////////////////////////////////
+
+ GenericNode & follow() const; ///< Access the referenced node
+
+ protected:
+
+ private:
+ explicit LinkNode(GenericNode & node);
+
+ virtual void v_help(std::ostream &) const;
+
+ GenericNode::ptr node_;
+ };
+
class SimpleCommandNode;
/** \brief Internal: Node creation helper traits
typedef BOOST_TYPEOF_TPL( senf_console_add_node(
* static_cast<DirectoryNode *>(0),
* static_cast<std::string const *>(0),
- * static_cast<Object const *>(0),
- 0) ) result_type;
+ * static_cast<Object *>(0),
+ 0) ) base_type;
+ typedef typename senf::remove_cvref<base_type>::type value_type;
- typedef typename boost::remove_reference<result_type>::type NodeType;
+ typedef typename value_type::node_type NodeType;
+ typedef typename value_type::return_type result_type;
/// Internal
struct Creator {
- static NodeType & create(DirectoryNode & node, std::string const & name,
- Object const & ob);
+ static result_type create(DirectoryNode & node, std::string const & name,
+ Object & ob);
};
};
typedef boost::iterator_range<ChildMap::const_iterator> ChildrenRange;
typedef ChildMap::const_iterator child_iterator;
+ typedef DirectoryNode node_type;
+ typedef DirectoryNode & return_type;
+
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///\{
\a name is empty, it is set to 'unnamed'. */
template <class Object>
- typename NodeCreateTraits<Object>::NodeType & add (std::string const & name,
+ typename NodeCreateTraits<Object>::result_type add(std::string const & name,
Object const & ob);
///< Generic child node factory
/**< This member is used to create a new child node of the
is not used but serves to disambiguate the
overloads). */
+ template <class Object>
+ typename NodeCreateTraits<Object>::result_type add(std::string const & name,
+ Object & ob);
+ ///< Generic child node factory
+ /**< \see add() */
+
GenericNode::ptr remove(std::string const & name);
///< Remove node \a name from the tree
/**< The returned pointer may either be discarded, which
be saved and/or re-attached at some other place in the
tree. */
+ bool hasChild(std::string const & name) const;
+ ///< \c true, if there is a child with name \a name
+
GenericNode & get(std::string const & name) const;
///< Get child node
/**< \throws UnknownNodeNameException if a child \a name
does not exist */
+ GenericNode & getLink(std::string const & name) const;
+ ///< Get child node without dereferencing links
+ /**< \throws UnknownNodeNameException if a child \a name
+ does not exist */
DirectoryNode & getDirectory(std::string const & name) const;
///< Get directory child node
DirectoryNode & mkdir(std::string const & name);
///< Create sub-directory node
- ChildrenRange children() const;
- ///< Return iterator range over all children.
+ ChildrenRange children() const; ///< Return iterator range over all children.
/**< The returned range is sorted by child name. */
- ///\}
- ///////////////////////////////////////////////////////////////////////////
+ ChildrenRange completions(std::string const & s) const;
+ ///< Return iterator range of completions for \a s
+ /**< The returned range is sorted by child name. */
- template <class ForwardRange>
- GenericNode & traverse(ForwardRange const & range);
- ///< Traverse node path starting at this node
- /**< The <tt>ForwardRange::value_type</tt> must be
- (convertible to) std::string. Each range element
- constitutes a step along the node traversal.
+ void link(std::string const & name, GenericNode & target);
- If the range starts with an empty element, the
- traversal is started at the root() node, otherwise it
- is started at \a this node. The traversal supports '.',
- '..' and ignores further empty elements. */
+ ///\}
+ ///////////////////////////////////////////////////////////////////////////
- DirectoryNode & doc(std::string const & doc);
- ///< Set node documentation
+ DirectoryNode & doc(std::string const & doc); ///< Set node documentation
ptr thisptr();
cptr thisptr() const;
friend DirectoryNode & root();
};
- BOOST_TYPEOF_REGISTER_TYPE(DirectoryNode);
-
/// Exception: Unknown node name
struct UnknownNodeNameException : public senf::Exception
{ UnknownNodeNameException() : senf::Exception("Unknown node name") {}};
{};
#endif
- struct SyntaxErrorException : public senf::Exception
- {
- explicit SyntaxErrorException(std::string const & msg = "");
-
- virtual char const * what() const throw();
- };
-
/** \brief Config/console tree command node
The CommandNode is the base-class for the tree leaf nodes. Concrete command node
To execute a command, CommandNode::operator()() or CommandNode::execute() is called.
+ Subclass instances of this node type are automatically created when adding commands to the
+ tree. See \ref console_commands.
+
\ingroup node_tree
*/
class CommandNode : public GenericNode
\param[in] output stream where result messages may be
written to
\param[in] arguments command arguments. This is a
- range of ranges of ArgumentToken instances. */
+ range of ranges of Token instances. */
void operator()(std::ostream & output, ParseCommandInfo const & command) const;
///< Execute the command
\param[in] output stream where result messages may be
written to
\param[in] arguments command arguments. This is a
- range of ranges of ArgumentToken instances. */
+ range of ranges of Token instances. */
ptr thisptr();
cptr thisptr() const;
/**< \param[in] output stream where result messages may be
written to
\param[in] arguments command arguments. This is a
- range of ranges of ArgumentToken instances. */
+ range of ranges of Token instances. */
private:
};
/** \brief Most simple CommandNode implementation
This CommandNode implementation simply forwards the \a output and \a arguments arguments to
- an arbitrary callback.
+ an arbitrary callback. Thus, it allows to add callbacks with the signature
+ \code
+ void callback(std::ostream & os, senf::console::ParseCommandInfo const & command)
+ { ... }
+ \endcode
+ to the tree.
- \ingroup node_tree
+ \ingroup console_commands
*/
class SimpleCommandNode : public CommandNode
{
typedef boost::function<void (std::ostream &, ParseCommandInfo const &)> Function;
+ typedef SimpleCommandNode node_type;
+ typedef SimpleCommandNode & return_type;
+
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///\{
};
#ifndef DOXYGEN
- template <class Function>
+
SimpleCommandNode & senf_console_add_node(DirectoryNode & node, std::string const & name,
- Function const & fn, ...);
+ SimpleCommandNode::Function fn, int);
+
#endif
- BOOST_TYPEOF_REGISTER_TYPE(SimpleCommandNode);
+}}
- DirectoryNode & root();
+#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
+
+BOOST_TYPEOF_REGISTER_TYPE(senf::console::DirectoryNode)
+BOOST_TYPEOF_REGISTER_TYPE(senf::console::SimpleCommandNode)
-}}
///////////////////////////////hh.e////////////////////////////////////////
#include "Node.cci"
-#include "Node.ct"
+//#include "Node.ct"
#include "Node.cti"
#endif