}
///////////////////////////////////////////////////////////////////////////
+// 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)
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"
}
///////////////////////////////////////////////////////////////////////////
+// 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()
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)
{}
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_
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.
*/
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
static ptr create(); ///< Create node object.
/**< You should normally use either mkdir() or
- ObjectDirectory instead of create() */
+ ScopedDirectory instead of create() */
///\}
///////////////////////////////////////////////////////////////////////////
{};
#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
///////////////////////////////////////////////////////////////////////////
- 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
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:
};
///\}
///////////////////////////////////////////////////////////////////////////
- virtual void operator()(std::ostream & output, Arguments const & arguments);
-
ptr thisptr();
cptr thisptr() const;
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_;
--- /dev/null
+// $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:
--- /dev/null
+// $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:
--- /dev/null
+// $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:
// 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////////////////////////////////////////
--- /dev/null
+// $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:
// 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>
}
///////////////////////////////////////////////////////////////////////////
-// 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>
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_
// 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
};
};
- /** \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
class MyClass
{
public:
- ObjectDirectory<MyClass> configDir;
+ ScopedDirectory<MyClass> configDir;
MyClass() : configDir(this)
{
};
\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
\ingroup node_tree
*/
- template <class Owner>
- class ObjectDirectory : public ObjectDirectoryBase
+ template <class Owner=void>
+ class ScopedDirectory : public ScopedDirectoryBase
{
public:
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///@{
- ObjectDirectory(Owner * owner);
- ~ObjectDirectory();
+ ScopedDirectory(Owner * owner);
///@}
///////////////////////////////////////////////////////////////////////////
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(
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
--- /dev/null
+// $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:
#include <iostream>
#include "Server.hh"
#include "Node.hh"
-#include "ObjectDirectory.hh"
+#include "ScopedDirectory.hh"
#include "../Scheduler/Scheduler.hh"
#include "../Utils/Logger/SenfLog.hh"
struct TestObject
{
- senf::console::ObjectDirectory<TestObject> dir;
+ senf::console::ScopedDirectory<TestObject> dir;
TestObject() : dir(this) {
dir.add("blub", &TestObject::blub)
(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;
}
#autotoc {
- width: 20em;
+ width: 30em;
background-color: #F5F5F5;
border: 1px solid #CCC;
padding: 0 1em;