HowTos/NewPacket: Remove old code from example
g0dil [Tue, 1 Apr 2008 18:51:31 +0000 (18:51 +0000)]
Console: Implement OverloadableCommandNode
Console: Make all virtual functions private
Console: Rename ObjectDirectory to ScopedDirectory
Console: Move non-template dependent ScopedDirectory members to ScopedDirectoryBase
Console: Provide owner-less void specialization of ScopedDirectory

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@772 270642c3-0616-0410-b53a-bc976706d245

14 files changed:
Console/Node.cc
Console/Node.cci
Console/Node.hh
Console/OverloadedCommand.cc [new file with mode: 0644]
Console/OverloadedCommand.cci [new file with mode: 0644]
Console/OverloadedCommand.hh [new file with mode: 0644]
Console/OverloadedCommand.test.cc [moved from Console/ObjectDirectory.test.cc with 52% similarity]
Console/ScopedDirectory.cci [new file with mode: 0644]
Console/ScopedDirectory.cti [moved from Console/ObjectDirectory.cti with 64% similarity]
Console/ScopedDirectory.hh [moved from Console/ObjectDirectory.hh with 83% similarity]
Console/ScopedDirectory.test.cc [new file with mode: 0644]
Console/testServer.cc
HowTos/NewPacket/Mainpage.dox
doclib/senf.css

index 5e1e427..1cd8d40 100644 (file)
@@ -117,6 +117,15 @@ prefix_ void senf::console::DirectoryNode::v_help(std::ostream & output)
 }
 
 ///////////////////////////////////////////////////////////////////////////
+// senf::console::SyntaxErrorException
+
+prefix_ char const * senf::console::SyntaxErrorException::what()
+    const throw()
+{
+    return message().empty() ? "syntax error" : message().c_str();
+}
+
+///////////////////////////////////////////////////////////////////////////
 // senf::console::SimpleCommandNode
 
 prefix_ void senf::console::SimpleCommandNode::v_help(std::ostream & output)
@@ -125,6 +134,13 @@ prefix_ void senf::console::SimpleCommandNode::v_help(std::ostream & output)
     output << doc_ << "\n";
 }
 
+prefix_ void senf::console::SimpleCommandNode::v_execute(std::ostream & output,
+                                                         Arguments const & arguments)
+    const
+{
+    fn_(output, arguments);
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "Node.mpp"
index 43954f3..5f824bd 100644 (file)
@@ -140,6 +140,13 @@ prefix_ senf::console::DirectoryNode::cptr senf::console::DirectoryNode::thisptr
 }
 
 ///////////////////////////////////////////////////////////////////////////
+// senf::console::SyntaxErrorException
+
+prefix_ senf::console::SyntaxErrorException::SyntaxErrorException(std::string const & msg)
+    : Exception(msg)
+{}
+
+///////////////////////////////////////////////////////////////////////////
 // senf::console::CommandNode
 
 prefix_ senf::console::CommandNode::ptr senf::console::CommandNode::thisptr()
@@ -156,15 +163,16 @@ prefix_ senf::console::CommandNode::cptr senf::console::CommandNode::thisptr()
 prefix_ senf::console::CommandNode::CommandNode()
 {}
 
-///////////////////////////////////////////////////////////////////////////
-// senf::console::SimpleCommandNode
-
-prefix_ void senf::console::SimpleCommandNode::operator()(std::ostream & output,
-                                                          Arguments const & arguments)
+prefix_ void senf::console::CommandNode::operator()(std::ostream & output,
+                                                    Arguments const & arguments)
+    const
 {
-    fn_(output, arguments);
+    v_execute(output, arguments);
 }
 
+///////////////////////////////////////////////////////////////////////////
+// senf::console::SimpleCommandNode
+
 prefix_ senf::console::SimpleCommandNode::SimpleCommandNode(Function const & fn)
     : fn_ (fn)
 {}
@@ -182,6 +190,17 @@ senf::console::SimpleCommandNode::doc(std::string const & doc)
     return *this;
 }
 
+prefix_ senf::console::SimpleCommandNode::ptr senf::console::SimpleCommandNode::thisptr()
+{
+    return boost::static_pointer_cast<SimpleCommandNode>(shared_from_this());
+}
+
+prefix_ senf::console::SimpleCommandNode::cptr senf::console::SimpleCommandNode::thisptr()
+    const
+{
+    return boost::static_pointer_cast<SimpleCommandNode const>(shared_from_this());
+}
+
 ///////////////////////////////cci.e///////////////////////////////////////
 #undef prefix_
 
index 0bed22b..961a1b8 100644 (file)
@@ -49,7 +49,7 @@
     public:
         // Declare a directory node (proxy) for use by this class. This must be public so we can add
         // it to the node tree later.
-        senf::console::ObjectDirectory<SomeClass> dir;
+        senf::console::ScopedDirectory<SomeClass> dir;
 
         SomeClass() : dir(this) 
         {
 
     Most objects will register several commands. So it makes sense for these objects to manage their
     own directory. Since directories are however allocated on the heap, they cannot be directly
-    added to a class. To facilitate this usage, the senf::console::ObjectDirectory is used. This
+    added to a class. To facilitate this usage, the senf::console::ScopedDirectory is used. This
     class provides a senf::console::DirectoryNode facade. Internally, it automatically creates a
     senf::console::DirectoryNode to which all calls are forwarded.
 
-    The senf::console::ObjectDirectory member should be declared public. This allows the user of the
+    The senf::console::ScopedDirectory member should be declared public. This allows the user of the
     class to add the node to the tree.
  */
 
@@ -324,8 +324,8 @@ namespace console {
         mkdir() or add(). Special add() members however allow externally allocated node objects.
 
         Nodes may be added to the tree only once, otherwise chaos will ensue. Since nodes are always
-        managed dynamically, there is a special ObjectDirectory proxy template which provides a
-        DirectoryNode facade. ObjectDirectory is used if a class wants to manage it's own directory
+        managed dynamically, there is a special ScopedDirectory proxy template which provides a
+        DirectoryNode facade. ScopedDirectory is used if a class wants to manage it's own directory
         as a data member.
 
         Every node is assigned a (new) name when it is added to a directory. If the directory
@@ -357,7 +357,7 @@ namespace console {
 
         static ptr create();            ///< Create node object.
                                         /**< You should normally use either mkdir() or
-                                             ObjectDirectory instead of create() */
+                                             ScopedDirectory instead of create() */
 
         ///\}
         ///////////////////////////////////////////////////////////////////////////
@@ -479,6 +479,13 @@ 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
@@ -504,8 +511,8 @@ namespace console {
 
         ///////////////////////////////////////////////////////////////////////////
 
-        virtual void operator()(std::ostream & output, Arguments const & arguments) = 0;
-                                        ///< Called to execute the command
+        void operator()(std::ostream & output, Arguments const & arguments) const;
+                                        ///< Execute the command
                                         /**< \param[in] output stream where result messages may be
                                                  written to
                                              \param[in] arguments command arguments. This is a
@@ -517,6 +524,16 @@ namespace console {
     protected:
         CommandNode();
 
+#ifndef DOXYGEN
+    private:
+#endif
+        virtual void v_execute(std::ostream & output, Arguments const & arguments) 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. */
+
     private:
     };
 
@@ -551,8 +568,6 @@ namespace console {
         ///\}
         ///////////////////////////////////////////////////////////////////////////
 
-        virtual void operator()(std::ostream & output, Arguments const & arguments);
-
         ptr thisptr();
         cptr thisptr() const;
 
@@ -563,6 +578,8 @@ namespace console {
 
     private:
         virtual void v_help(std::ostream & output) const;
+        virtual void v_execute(std::ostream & output, Arguments const & arguments) const;
+        
 
         Function fn_;
         std::string doc_;
diff --git a/Console/OverloadedCommand.cc b/Console/OverloadedCommand.cc
new file mode 100644 (file)
index 0000000..30e7fbb
--- /dev/null
@@ -0,0 +1,98 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief OverloadedCommand non-inline non-template implementation */
+
+#include "OverloadedCommand.hh"
+//#include "OverloadedCommand.ih"
+
+// Custom includes
+
+//#include "OverloadedCommand.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::OverloadedCommandNode
+
+prefix_ void senf::console::OverloadedCommandNode::v_help(std::ostream & os)
+    const
+{
+    os << doc_;
+    Overloads::const_iterator i (overloads_.begin());
+    Overloads::const_iterator const i_end (overloads_.end());
+    for (; i != i_end; ++i) {
+        os << "\n\n";
+        (*i)->help(os);
+    }
+}
+
+prefix_ void senf::console::OverloadedCommandNode::v_execute(std::ostream & output,
+                                                             Arguments const & arguments)
+    const
+{
+    Overloads::const_iterator i (overloads_.begin());
+    Overloads::const_iterator const i_end (overloads_.end());
+    SyntaxErrorException err;
+    for (; i != i_end; ++i) {
+        try {
+            (**i)(output, arguments);
+            return;
+        }
+        catch (SyntaxErrorException & ex) {
+            err = ex;
+        };
+    }
+    throw err;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::SimpleCommandOverload
+
+prefix_ void senf::console::SimpleCommandOverload::v_help(std::ostream & os)
+    const
+{
+    os << doc_;
+}
+
+prefix_ void senf::console::SimpleCommandOverload::v_execute(std::ostream & os,
+                                                             Arguments const & arguments)
+    const
+{
+    fn_(os, arguments);
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "OverloadedCommand.mpp"
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
diff --git a/Console/OverloadedCommand.cci b/Console/OverloadedCommand.cci
new file mode 100644 (file)
index 0000000..21add3b
--- /dev/null
@@ -0,0 +1,126 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief OverloadedCommand inline non-template implementation */
+
+//#include "OverloadedCommand.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::CommandOverload
+
+prefix_ senf::console::CommandOverload::~CommandOverload()
+{}
+
+prefix_ void senf::console::CommandOverload::operator()(std::ostream & os,
+                                                        Arguments const & arguments)
+{
+    v_execute(os, arguments);
+}
+
+prefix_ void senf::console::CommandOverload::help(std::ostream & os)
+{
+    v_help(os);
+}
+
+prefix_ senf::console::OverloadedCommandNode & senf::console::CommandOverload::node()
+{
+    SENF_ASSERT( node_ );
+    return *node_;
+}
+
+prefix_ senf::console::CommandOverload::CommandOverload()
+    : node_(0)
+{}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::OverloadedCommandNode
+
+prefix_ senf::console::OverloadedCommandNode::ptr senf::console::OverloadedCommandNode::create()
+{
+    return ptr(new OverloadedCommandNode());
+}
+
+prefix_ void senf::console::OverloadedCommandNode::add(CommandOverload::ptr overload)
+{
+    overloads_.push_back(overload);
+}
+
+prefix_ senf::console::OverloadedCommandNode::ptr senf::console::OverloadedCommandNode::thisptr()
+{
+    return boost::static_pointer_cast<OverloadedCommandNode>(shared_from_this());
+}
+
+prefix_ senf::console::OverloadedCommandNode::cptr senf::console::OverloadedCommandNode::thisptr()
+    const
+{
+    return boost::static_pointer_cast<OverloadedCommandNode const>(shared_from_this());
+}
+
+prefix_ senf::console::OverloadedCommandNode &
+senf::console::OverloadedCommandNode::doc(std::string const & doc)
+{
+    doc_ = doc;
+    return *this;
+}
+
+prefix_ senf::console::OverloadedCommandNode::OverloadedCommandNode()
+{}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::SimpleCommandOverload
+
+prefix_ senf::console::SimpleCommandOverload::ptr
+senf::console::SimpleCommandOverload::create(Function fn)
+{
+    return ptr(new SimpleCommandOverload(fn));
+}
+
+prefix_ senf::console::SimpleCommandOverload &
+senf::console::SimpleCommandOverload::doc(std::string const & doc)
+{
+    doc_ = doc;
+    return *this;
+}
+
+prefix_ senf::console::SimpleCommandOverload::SimpleCommandOverload(Function fn)
+    : fn_ (fn)
+{}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
diff --git a/Console/OverloadedCommand.hh b/Console/OverloadedCommand.hh
new file mode 100644 (file)
index 0000000..a255eb5
--- /dev/null
@@ -0,0 +1,182 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief OverloadedCommand public header */
+
+#ifndef HH_OverloadedCommand_
+#define HH_OverloadedCommand_ 1
+
+// Custom includes
+#include "Node.hh"
+#include <boost/intrusive_ptr.hpp>
+#include "../Utils/intrusive_refcount.hh"
+
+//#include "OverloadedCommand.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace console {
+
+    class OverloadedCommandNode;
+
+    /** \brief
+      */
+    class CommandOverload
+        : public senf::intrusive_refcount
+    {
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        // Types
+
+        typedef boost::intrusive_ptr<CommandOverload> ptr;
+        typedef CommandNode::Arguments Arguments;
+
+        ///////////////////////////////////////////////////////////////////////////
+
+        virtual ~CommandOverload();
+
+        void operator()(std::ostream & os, Arguments const & arguments);
+        void help(std::ostream & os);
+
+        OverloadedCommandNode & node();
+
+    protected:
+        CommandOverload();
+
+#ifndef DOXYGEN
+    private:
+#endif
+        virtual void v_help(std::ostream & os) const = 0;
+        virtual void v_execute(std::ostream & os, Arguments const & arguments) const = 0;
+
+    private:
+        OverloadedCommandNode * node_;
+
+        friend class OverloadedCommandNode;
+    };
+
+    /** \brief Command node which allows multiple registered callbacks
+
+        OverloadedCommand is like SimpleCommand but allows to register multiple commands to a single
+        node. This works by calling each command in the list consecutively until no 'SyntaxError'
+        exception is thrown. 
+
+        \warning For this to work, the commands <b>must</b> do all syntax checking before doing any
+            operation
+
+        \ingroup node_tree
+      */
+    class OverloadedCommandNode
+        : public CommandNode
+    {
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        // Types
+
+        typedef boost::shared_ptr<OverloadedCommandNode> ptr;
+        typedef boost::shared_ptr<OverloadedCommandNode const> cptr;
+        typedef boost::weak_ptr<OverloadedCommandNode> weak_ptr;
+
+        ///////////////////////////////////////////////////////////////////////////
+        ///\name Structors and default members
+        ///@{
+
+        static ptr create();
+
+        ///@}
+        ///////////////////////////////////////////////////////////////////////////
+
+        void add(CommandOverload::ptr overload);
+
+        ptr thisptr();
+        cptr thisptr() const;
+
+        OverloadedCommandNode & doc(std::string const & doc);
+
+    protected:
+
+    private:
+        OverloadedCommandNode();
+
+        virtual void v_help(std::ostream & output) const;
+        virtual void v_execute(std::ostream & output, Arguments const & arguments) const;
+
+        typedef std::vector<CommandOverload::ptr> Overloads;
+
+        Overloads overloads_;
+        std::string doc_;
+    };
+
+    /** \brief
+      */
+    class SimpleCommandOverload
+        : public CommandOverload
+    {
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        // Types
+
+        typedef boost::intrusive_ptr<SimpleCommandOverload> ptr;
+        typedef boost::function<void (std::ostream &, Arguments const &)> Function;
+
+        ///////////////////////////////////////////////////////////////////////////
+        ///\name Structors and default members
+        ///@{
+
+        static SimpleCommandOverload::ptr create(Function fn);
+
+        ///@}
+        ///////////////////////////////////////////////////////////////////////////
+
+        SimpleCommandOverload & doc(std::string const & doc);
+
+    protected:
+
+    private:
+        SimpleCommandOverload(Function fn);
+
+        virtual void v_help(std::ostream & os) const;
+        virtual void v_execute(std::ostream & os, Arguments const & arguments) const;
+
+        Function fn_;
+        std::string doc_;
+    };
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "OverloadedCommand.cci"
+//#include "OverloadedCommand.ct"
+//#include "OverloadedCommand.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
similarity index 52%
rename from Console/ObjectDirectory.test.cc
rename to Console/OverloadedCommand.test.cc
index a8e99af..2879201 100644 (file)
 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 /** \file
-    \brief ObjectDirectory.test unit tests */
+    \brief OverloadedCommand.test unit tests */
 
-//#include "ObjectDirectory.test.hh"
-//#include "ObjectDirectory.test.ih"
+//#include "OverloadedCommand.test.hh"
+//#include "OverloadedCommand.test.ih"
 
 // Custom includes
 #include <sstream>
-#include "ObjectDirectory.hh"
+#include "OverloadedCommand.hh"
 
 #include <boost/test/auto_unit_test.hpp>
 #include <boost/test/test_tools.hpp>
 ///////////////////////////////cc.p////////////////////////////////////////
 
 namespace {
-    struct TestObject {
-        typedef TestObject Self;
-
-        senf::console::ObjectDirectory<Self> dir;
-        TestObject() : dir(this) {
-            dir.add("member", &Self::member);
-        }
-
-        void member(std::ostream & os, senf::console::CommandNode::Arguments const &) {
-            os << "member";
-        }
-    };
-}
 
-BOOST_AUTO_UNIT_TEST(objectDirectory)
-{
+    void fn1(std::ostream &, senf::console::CommandOverload::Arguments const &)
+    {
+        throw senf::console::SyntaxErrorException("fn1 error");
+    }
+
+    void fn2(std::ostream &, senf::console::CommandOverload::Arguments const &)
+    {
+        throw senf::console::SyntaxErrorException("fn2 error");
+    }
+
+    void fn3(std::ostream & os, senf::console::CommandOverload::Arguments const &)
     {
-        TestObject ob;
-        senf::console::root().add("ob",ob.dir);
-        std::stringstream ss;
-        senf::console::ParseCommandInfo info;
-        senf::console::root()["ob"]("member")(ss, info.arguments());
-        BOOST_CHECK_EQUAL( ss.str(), "member" );
+        os << "fn3\n";
     }
-    BOOST_CHECK_THROW( senf::console::root()["ob"], senf::console::UnknownNodeNameException );
+
+}
+
+BOOST_AUTO_UNIT_TEST(overladedCommand)
+{
+    senf::console::OverloadedCommandNode & cmd (
+        senf::console::root().add("overload", senf::console::OverloadedCommandNode::create()));
+    cmd.add(senf::console::SimpleCommandOverload::create(&fn1));
+    cmd.add(senf::console::SimpleCommandOverload::create(&fn2));
+
+    senf::console::ParseCommandInfo info;
+    std::stringstream ss;
+    BOOST_CHECK_THROW( senf::console::root()("overload")(ss, info.arguments()),
+                       senf::console::SyntaxErrorException );
+
+    cmd.add(senf::console::SimpleCommandOverload::create(&fn3));
+    BOOST_CHECK_NO_THROW( senf::console::root()("overload")(ss, info.arguments()) );
+    BOOST_CHECK_EQUAL( ss.str(), "fn3\n" );
+
+    cmd.unlink();
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
diff --git a/Console/ScopedDirectory.cci b/Console/ScopedDirectory.cci
new file mode 100644 (file)
index 0000000..b6acd78
--- /dev/null
@@ -0,0 +1,109 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief ScopedDirectory inline non-template implementation */
+
+//#include "ScopedDirectory.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ScopedDirectoryBase
+
+prefix_ senf::console::DirectoryNode & senf::console::ScopedDirectoryBase::node()
+    const
+{
+    return *node_;
+}
+
+prefix_ senf::console::GenericNode::ptr
+senf::console::ScopedDirectoryBase::remove(std::string const & name)
+{
+   return node().remove(name);
+}
+
+prefix_ senf::console::DirectoryNode &
+senf::console::ScopedDirectoryBase::operator[](std::string const & name)
+    const
+{
+    return node()[name];
+}
+
+prefix_ senf::console::CommandNode &
+senf::console::ScopedDirectoryBase::operator()(std::string const & name)
+    const
+{
+    return node()(name);
+}
+
+prefix_ senf::console::GenericNode &
+senf::console::ScopedDirectoryBase::get(std::string const & name)
+    const
+{
+    return node().get(name);
+}
+
+prefix_ senf::console::DirectoryNode &
+senf::console::ScopedDirectoryBase::mkdir(std::string const & name)
+{
+    return node().mkdir(name);
+}
+
+prefix_ senf::console::DirectoryNode::ChildrenRange
+senf::console::ScopedDirectoryBase::children()
+    const
+{
+    return node().children();
+}
+
+prefix_ senf::console::DirectoryNode &
+senf::console::ScopedDirectoryBase::doc(std::string const & doc)
+{
+    return node().doc(doc);
+}
+
+prefix_ senf::console::ScopedDirectoryBase::ScopedDirectoryBase()
+    : node_ (DirectoryNode::create())
+{}
+
+prefix_ senf::console::ScopedDirectoryBase::~ScopedDirectoryBase()
+{
+    node_->unlink();
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
similarity index 64%
rename from Console/ObjectDirectory.cti
rename to Console/ScopedDirectory.cti
index c3f3e0d..87ce190 100644 (file)
@@ -21,9 +21,9 @@
 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 /** \file
-    \brief ObjectDirectory inline template implementation */
+    \brief ScopedDirectory inline template implementation */
 
-//#include "ObjectDirectory.ih"
+//#include "ScopedDirectory.ih"
 
 // Custom includes
 #include <boost/bind.hpp>
@@ -45,85 +45,21 @@ senf::console::OwnerNodeCreateTraits<Owner,Object>::Creator::create(DirectoryNod
 }
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::console::ObjectDirectory<Owner>
+// senf::console::ScopedDirectory<Owner>
 
 template <class Owner>
-prefix_ senf::console::ObjectDirectory<Owner>::ObjectDirectory(Owner * owner)
-    : node_ (DirectoryNode::create()), owner_ (owner)
-{}
-
-template <class Owner>
-prefix_ senf::console::ObjectDirectory<Owner>::~ObjectDirectory()
+prefix_ senf::console::ScopedDirectory<Owner>::ScopedDirectory(Owner * owner)
+    : owner_ (owner)
 {
-    node_->unlink();
+    SENF_ASSERT(owner_);
 }
 
 template <class Owner>
 template <class Object>
 prefix_ typename senf::console::OwnerNodeCreateTraits<Owner, Object>::NodeType &
-senf::console::ObjectDirectory<Owner>::add(std::string const & name, Object const & ob)
-{
-    return OwnerNodeCreateTraits<Owner, Object>::Creator::create(*node_, *owner_, name, ob);
-}
-
-template <class Owner>
-prefix_ senf::console::GenericNode::ptr
-senf::console::ObjectDirectory<Owner>::remove(std::string const & name)
-{
-   return node().remove(name);
-}
-
-template <class Owner>
-prefix_ senf::console::DirectoryNode &
-senf::console::ObjectDirectory<Owner>::operator[](std::string const & name)
-    const
-{
-    return node()[name];
-}
-
-template <class Owner>
-prefix_ senf::console::CommandNode &
-senf::console::ObjectDirectory<Owner>::operator()(std::string const & name)
-    const
-{
-    return node()(name);
-}
-
-template <class Owner>
-prefix_ senf::console::GenericNode &
-senf::console::ObjectDirectory<Owner>::get(std::string const & name)
-    const
-{
-    return node().get(name);
-}
-
-template <class Owner>
-prefix_ senf::console::DirectoryNode &
-senf::console::ObjectDirectory<Owner>::mkdir(std::string const & name)
-{
-    return node().mkdir(name);
-}
-
-template <class Owner>
-prefix_ senf::console::DirectoryNode::ChildrenRange
-senf::console::ObjectDirectory<Owner>::children()
-    const
-{
-    return node().children();
-}
-
-template <class Owner>
-prefix_ senf::console::DirectoryNode &
-senf::console::ObjectDirectory<Owner>::doc(std::string const & doc)
+senf::console::ScopedDirectory<Owner>::add(std::string const & name, Object const & ob)
 {
-    return node.doc(doc);
-}
-
-template <class Owner>
-prefix_ senf::console::DirectoryNode & senf::console::ObjectDirectory<Owner>::node()
-    const
-{
-    return *node_;
+    return OwnerNodeCreateTraits<Owner, Object>::Creator::create(node(), *owner_, name, ob);
 }
 
 template <class Owner, class Function>
@@ -146,11 +82,21 @@ senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & n
 template <class Node>
 prefix_ senf::console::DirectoryNode & senf::console::
 senf_console_add_node(DirectoryNode & dir, std::string const & name, Node const & node, int,
-                      typename boost::enable_if< boost::is_convertible<Node*, ObjectDirectoryBase*> >::type *)
+                      typename boost::enable_if< boost::is_convertible<Node*, ScopedDirectoryBase*> >::type *)
 {
     return dir.add(name, node.node().thisptr());
 }
 
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ScopedDirectory<void>
+
+template <class Object>
+prefix_ typename senf::console::NodeCreateTraits<Object>::NodeType &
+senf::console::ScopedDirectory<void>::add(std::string const & name, Object const & ob)
+{
+    return node().add(name, ob);
+}
+
 ///////////////////////////////cti.e///////////////////////////////////////
 #undef prefix_
 
similarity index 83%
rename from Console/ObjectDirectory.hh
rename to Console/ScopedDirectory.hh
index 1845a06..cec50db 100644 (file)
 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 /** \file
-    \brief ObjectDirectory public header */
+    \brief ScopedDirectory public header */
 
-#ifndef HH_ObjectDirectory_
-#define HH_ObjectDirectory_ 1
+#ifndef HH_ScopedDirectory_
+#define HH_ScopedDirectory_ 1
 
 // Custom includes
 #include <boost/utility.hpp>
 #include <boost/type_traits/is_convertible.hpp>
 #include "Node.hh"
 
-//#include "ObjectDirectory.mpp"
+//#include "ScopedDirectory.mpp"
 ///////////////////////////////hh.p////////////////////////////////////////
 
 namespace senf {
 namespace console {
 
-    /** \brief Internal: Node creation helper traits (ObjectDirectory proxy)
+    /** \brief Internal: Node creation helper traits (ScopedDirectory proxy)
         
         This class is used like NodeCreateTraits to customize the child node creation. This trait
-        class is used however by the ObjectDirectory proxy.
+        class is used however by the ScopedDirectory proxy.
      */
     template <class Owner, class Object>
     struct OwnerNodeCreateTraits
@@ -60,13 +60,38 @@ namespace console {
         };
     };
     
-    /** \brief Internal: Marker base class for all ObjectDirectory proxies
+    /** \brief Internal: Marker base class for all ScopedDirectory proxies
      */
-    struct ObjectDirectoryBase {};
+    class ScopedDirectoryBase
+    {
+    public:
+        DirectoryNode & node() const;   ///< Access the proxied DirectoryNode
+
+        ///////////////////////////////////////////////////////////////////////////
+        ///\name Proxied members (see DirectoryNode)
+        ///\{
+
+        GenericNode::ptr remove(std::string const & name);
+        DirectoryNode & operator[](std::string const & name) const;
+        CommandNode & operator()(std::string const & name) const;
+        GenericNode & get(std::string const & name) const;
+        DirectoryNode & mkdir(std::string const & name);
+        DirectoryNode::ChildrenRange children() const;
+        DirectoryNode & doc(std::string const & doc);
+
+        ///\}
+
+    protected:
+        ScopedDirectoryBase();
+        ~ScopedDirectoryBase();
+
+    private:
+        DirectoryNode::ptr node_;
+    };
 
     /** \brief DirectoryNode member proxy
 
-        ObjectDirectory is used whenever a class wants to manage it's own directory. The class
+        ScopedDirectory is used whenever a class wants to manage it's own directory. The class
         allows to declare the directory as a public member object. This allows the user of the class
         to register the directory in the command tree. By using the proxy, the node is automatically
         detached from the tree (and thereby destroyed) when the object (and thereby the proxy) is
@@ -76,7 +101,7 @@ namespace console {
         class MyClass
         {
         public:
-            ObjectDirectory<MyClass> configDir;
+            ScopedDirectory<MyClass> configDir;
 
             MyClass() : configDir(this) 
             {
@@ -85,9 +110,9 @@ namespace console {
         };
         \endcode
 
-        The ObjectDirectory proxy implements 'add()' to add new children to the proxied
+        The ScopedDirectory proxy implements 'add()' to add new children to the proxied
         DirectoryNode. All add() variants supported by DirectoryNode are supported by
-        ObjectDirectory.
+        ScopedDirectory.
 
         \idea This proxy could be made obsolete by allowing to allocate node objects
             statically. This could be achieved by moving back to an intrusive_ptr implementation for
@@ -98,8 +123,8 @@ namespace console {
 
         \ingroup node_tree
       */
-    template <class Owner>
-    class ObjectDirectory : public ObjectDirectoryBase
+    template <class Owner=void>
+    class ScopedDirectory : public ScopedDirectoryBase
     {
     public:
         ///////////////////////////////////////////////////////////////////////////
@@ -111,8 +136,7 @@ namespace console {
         ///\name Structors and default members
         ///@{
 
-        ObjectDirectory(Owner * owner);
-        ~ObjectDirectory();
+        ScopedDirectory(Owner * owner);
 
         ///@}
         ///////////////////////////////////////////////////////////////////////////
@@ -127,29 +151,21 @@ namespace console {
                                              implementation just forwards the call to the proxied
                                              directory node. */
 
-        DirectoryNode & node() const;   ///< Access the proxied DirectoryNode
-
-        ///////////////////////////////////////////////////////////////////////////
-        ///\name Proxied members (see DirectoryNode)
-        ///\{
-
-        GenericNode::ptr remove(std::string const & name);
-        DirectoryNode & operator[](std::string const & name) const;
-        CommandNode & operator()(std::string const & name) const;
-        GenericNode & get(std::string const & name) const;
-        DirectoryNode & mkdir(std::string const & name);
-        DirectoryNode::ChildrenRange children() const;
-        DirectoryNode & doc(std::string const & doc);
-
-        ///\}
-
     protected:
 
     private:
-        DirectoryNode::ptr node_;
         Owner * owner_;
     };
 
+    template <>
+    class ScopedDirectory<void> : public ScopedDirectoryBase
+    {
+    public:
+        template <class Object>
+        typename NodeCreateTraits<Object>::NodeType & add(std::string const & name,
+                                                          Object const & ob);
+    };
+
 #ifndef DOXYGEN
     template <class Owner, class Function>
     SimpleCommandNode & senf_console_add_node(
@@ -163,15 +179,15 @@ namespace console {
     template <class Node>
     DirectoryNode & senf_console_add_node(
         DirectoryNode & dir, std::string const & name, Node const & node, int, 
-        typename boost::enable_if< boost::is_convertible<Node*, ObjectDirectoryBase*> >::type * = 0);
+        typename boost::enable_if< boost::is_convertible<Node*, ScopedDirectoryBase*> >::type * = 0);
 #endif
 
 }}
 
 ///////////////////////////////hh.e////////////////////////////////////////
-//#include "ObjectDirectory.cci"
-//#include "ObjectDirectory.ct"
-#include "ObjectDirectory.cti"
+#include "ScopedDirectory.cci"
+//#include "ScopedDirectory.ct"
+#include "ScopedDirectory.cti"
 #endif
 
 \f
diff --git a/Console/ScopedDirectory.test.cc b/Console/ScopedDirectory.test.cc
new file mode 100644 (file)
index 0000000..4a3ce75
--- /dev/null
@@ -0,0 +1,135 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief ScopedDirectory.test unit tests */
+
+//#include "ScopedDirectory.test.hh"
+//#include "ScopedDirectory.test.ih"
+
+// Custom includes
+#include <sstream>
+#include "ScopedDirectory.hh"
+#include <boost/iterator/transform_iterator.hpp>
+
+#include <boost/test/auto_unit_test.hpp>
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+namespace {
+    struct TestObject {
+        typedef TestObject Self;
+
+        senf::console::ScopedDirectory<Self> dir;
+        TestObject() : dir(this) {
+            dir.add("member", &Self::member);
+        }
+
+        void member(std::ostream & os, senf::console::CommandNode::Arguments const &) {
+            os << "member";
+        }
+    };
+}
+
+BOOST_AUTO_UNIT_TEST(scopedDirectory)
+{
+    {
+        TestObject ob;
+        senf::console::root().add("ob",ob.dir);
+        std::stringstream ss;
+        senf::console::ParseCommandInfo info;
+        senf::console::root()["ob"]("member")(ss, info.arguments());
+        BOOST_CHECK_EQUAL( ss.str(), "member" );
+    }
+    BOOST_CHECK_THROW( senf::console::root()["ob"], senf::console::UnknownNodeNameException );
+}
+
+namespace {
+    void callback(std::ostream & os, senf::console::CommandNode::Arguments const &) {
+        os << "cb";
+    }
+}
+
+BOOST_AUTO_UNIT_TEST(scopedDirectoryVoid)
+{
+    {
+        senf::console::ScopedDirectory<> dir;
+        senf::console::root().add("dir", dir);
+        dir.add("cb", &callback);
+        std::stringstream ss;
+        senf::console::ParseCommandInfo info;
+        senf::console::root()["dir"]("cb")(ss, info.arguments());
+        BOOST_CHECK_EQUAL( ss.str(), "cb" );
+    }
+    BOOST_CHECK_THROW( senf::console::root()["dir"],
+                       senf::console::UnknownNodeNameException );
+}
+
+namespace {
+    template <class T>
+    struct select1st {
+        typedef T result_type;
+        template <class U> result_type operator()(U const & u) const { return u.first; }
+    };
+}
+
+BOOST_AUTO_UNIT_TEST(scopedDirectoryBase)
+{
+    {
+        senf::console::ScopedDirectory<> dir;
+        senf::console::root().add("dir", dir);
+        dir.mkdir("foo");
+        dir.add("cb", &callback);
+        BOOST_CHECK( &dir["foo"] == &dir.get("foo") );
+        BOOST_CHECK( &dir("cb") == &dir.get("cb") );
+        
+        char const * const children[] = { "cb", "foo" };
+        BOOST_CHECK_EQUAL_COLLECTIONS( 
+            boost::make_transform_iterator(dir.children().begin(),
+                                           select1st<std::string const &>()),
+            boost::make_transform_iterator(dir.children().end(),
+                                           select1st<std::string const &>()),
+            children, 
+            children+sizeof(children)/sizeof(children[0]) );
+        
+        dir.doc("dir");
+        std::stringstream ss;
+        dir.node().help(ss);
+        BOOST_CHECK_EQUAL( ss.str(), "dir\n" );
+    }
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
index dc40117..b7d5124 100644 (file)
@@ -30,7 +30,7 @@
 #include <iostream>
 #include "Server.hh"
 #include "Node.hh"
-#include "ObjectDirectory.hh"
+#include "ScopedDirectory.hh"
 #include "../Scheduler/Scheduler.hh"
 #include "../Utils/Logger/SenfLog.hh"
 
@@ -55,7 +55,7 @@ namespace {
 
     struct TestObject
     {
-        senf::console::ObjectDirectory<TestObject> dir;
+        senf::console::ScopedDirectory<TestObject> dir;
 
         TestObject() : dir(this) {
             dir.add("blub", &TestObject::blub)
index bd659ab..e519e91 100644 (file)
                                                           (senf::VoidPacketParser)
                                                           (GREPacketParser_OptFields) );
 
-        typedef version__t version_t;
-        version_t::value_type version() const { return version_(); }
-
         bool valid() const { return version() == 0 && reserved0_5bits_() == 0; }
 
         typedef GREPacketParser_OptFields::checksum_t checksum_t;
index fe51388..1783cc1 100644 (file)
@@ -513,7 +513,7 @@ p.commalist {
 }
 
 #autotoc {
-        width: 20em;
+        width: 30em;
         background-color: #F5F5F5;
         border: 1px solid #CCC;
         padding: 0 1em;