Utils: Document new utilities
[senf.git] / Console / Node.hh
index 961a1b8..939113b 100644 (file)
@@ -23,7 +23,7 @@
 /** \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
@@ -38,7 +38,7 @@
 
     \code
     // Define callback function.
-    void mycommand(std::ostream & os, senf::console::Arguments const & args)
+    void mycommand(std::ostream & os, senf::console::ParseCommandInfo const & command)
     {
         // ...
         os << "!! Important message ...\n";
@@ -61,7 +61,7 @@
                 .doc("Do the member operation");
         }
 
-        void member(std::ostream & os, senf::console::Arguments const & args)
+        void member(std::ostream & os, senf::console::ParseCommandInfo const & command)
         {
             // ...
         }
     \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.
     
     \code
-    void callback(std::ostream & os, senf::console::Arguments const & args) { ... }
+    void callback(std::ostream & os, senf::console::ParseCommandInfo const & command) { ... }
     // ...
     myDirectory.add("foo",&callback);
     \endcode
     adding the node to the tree. If the name is empty or non-unique, a unique name will be
     automatically provided.
 
-    To remove a node from the tree, just use the nodes senf::console::GenericNode::unlink()
-    member. This call removes the node from it's parent and returns a (smart) node pointer.
+    To remove a node from the tree, just use the nodes senf::console::GenericNode::unlink() or the
+    parents senf::console::DirectoryNode::remove() member. This call removes the node from it's
+    parent and returns a (smart) node pointer.
 
     \li If you ignore the return value, the node (and it's children) will be deleted.
     \li Alternatively, you may store away the node and re-attach it later.
     \li To rename a node, unlink and re-add it with a different name.
 
     \code
-    myDirectory.add("bar", myDirectory("foo").unlink());
+    myDirectory.add("bar", myDirectory.remove("foo"));
     \endcode
 
     \subsection console_node_param Assigning additional node parameters
     Another possibility is to traverse the tree explicitly. For this purpose, the operators '[]' and
     '()' have been overloaded in senf::console::DirectoryNode.
     \code
+    senf::console::root().getDirectory("myDirectory").getCommand("foo")
+    \\ or more concise but otherwise completely identical
     senf::console::root()["myDirectory"]("foo")
     \endcode
-    The '[]' operator will return a senf::console::DirectoryNode whereas '()' will return a
-    senf::console::CommandNode. If the node is not found or is not of the correct type, an exception
-    will be raised.
+
+    getDirectory and the '[]' operator will return a senf::console::DirectoryNode whereas getCommand
+    and the '()' operator will return a senf::console::CommandNode. If the node is not found or is
+    not of the correct type, an exception will be raised.
 
     \section console_object_dir Assigning a directory to an object instance
 
 #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
@@ -255,6 +262,10 @@ namespace console {
         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
@@ -268,6 +279,20 @@ namespace console {
         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();
 
@@ -290,6 +315,47 @@ namespace console {
         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
@@ -303,15 +369,17 @@ namespace console {
         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);
         };
     };
 
@@ -351,6 +419,9 @@ namespace console {
         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
         ///\{
@@ -374,7 +445,7 @@ namespace console {
                                              \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
@@ -400,6 +471,12 @@ namespace console {
                                              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
@@ -407,49 +484,66 @@ namespace console {
                                              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
+                                        /**< Same as operator[]
+                                             \throws UnknownNodeNameException if a child \a name
+                                                 does not exist. 
+                                             \throws std::bad_cast if the child \a name is not a
+                                                 directory node. */
+        
         DirectoryNode & operator[](std::string const & name) const;
                                         ///< Get directory child node
-                                        /**< \throws UnknownNodeNameException if a child \a name
+                                        /**< Same as getDirectory
+                                             \throws UnknownNodeNameException if a child \a name
                                                  does not exist. 
                                              \throws std::bad_cast if the child \a name is not a
                                                  directory node. */
 
-        CommandNode & operator()(std::string const & name) const;
+        CommandNode & getCommand(std::string const & name) const;
                                         ///< Get command child node
-                                        /**< \throws UnknownNodeNameException if a child \a name
+                                        /**< Same as operator()
+                                             \throws UnknownNodeNameException if a child \a name
                                                  does not exist
                                              \throws std::bad_cast if the child \a name is not a
                                                  command node. */
 
-        GenericNode & get(std::string const & name) const;
-                                        ///< Get child node
-                                        /**< \throws UnknownNodeNameException if a child \a name
-                                                 does not exist */
+        CommandNode & operator()(std::string const & name) const;
+                                        ///< Get command child node
+                                        /**< Same as getCommand()
+                                             \throws UnknownNodeNameException if a child \a name
+                                                 does not exist
+                                             \throws std::bad_cast if the child \a name is not a
+                                                 command 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>FordwareRange::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;
@@ -467,8 +561,6 @@ namespace console {
         friend DirectoryNode & root();
     };
 
-    BOOST_TYPEOF_REGISTER_TYPE(DirectoryNode);
-
     /// Exception: Unknown node name
     struct UnknownNodeNameException : public senf::Exception
     { UnknownNodeNameException() : senf::Exception("Unknown node name") {}};
@@ -479,20 +571,15 @@ namespace console {
     {};
 #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
         implementations are derived from this class.
 
-        To execute a command, CommandNode::operator()() is called. This abstract virtual function
-        must be implemented in a derived class.
+        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
       */
@@ -507,16 +594,23 @@ namespace console {
         typedef boost::shared_ptr<CommandNode const> cptr;
         typedef boost::weak_ptr<CommandNode> weak_ptr;
 
-        typedef ParseCommandInfo::ArgumentsRange Arguments;
-
         ///////////////////////////////////////////////////////////////////////////
 
-        void operator()(std::ostream & output, Arguments const & arguments) const;
+        void execute(std::ostream & output, ParseCommandInfo const & command) const;
                                         ///< Execute the command
-                                        /**< \param[in] output stream where result messages may be
+                                        /**< Same as operator()()
+                                             \param[in] output stream where result messages may be
+                                                 written to
+                                             \param[in] arguments command arguments. This is a
+                                                 range of ranges of Token instances. */
+
+        void operator()(std::ostream & output, ParseCommandInfo const & command) const;
+                                        ///< Execute the command
+                                        /**< Same as execute()
+                                             \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;
@@ -527,24 +621,27 @@ namespace console {
 #ifndef DOXYGEN
     private:
 #endif
-        virtual void v_execute(std::ostream & output, Arguments const & arguments) const = 0;
+        virtual void v_execute(std::ostream & output, ParseCommandInfo const & command) const = 0;
                                         ///< Called to 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. */
 
     private:
     };
 
-    typedef CommandNode::Arguments Arguments;
-
     /** \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
     {
@@ -557,7 +654,10 @@ namespace console {
         typedef boost::shared_ptr<SimpleCommandNode const> cptr;
         typedef boost::weak_ptr<SimpleCommandNode> weak_ptr;
 
-        typedef boost::function<void (std::ostream &, Arguments const &)> Function;
+        typedef boost::function<void (std::ostream &, ParseCommandInfo const &)> Function;
+
+        typedef SimpleCommandNode node_type;
+        typedef SimpleCommandNode & return_type;
 
         ///////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
@@ -578,7 +678,7 @@ namespace console {
 
     private:
         virtual void v_help(std::ostream & output) const;
-        virtual void v_execute(std::ostream & output, Arguments const & arguments) const;
+        virtual void v_execute(std::ostream & output, ParseCommandInfo const & command) const;
         
 
         Function fn_;
@@ -586,20 +686,23 @@ namespace console {
     };
 
 #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