Skip to content
Snippets Groups Projects
Commit 07f81ae8 authored by g0dil's avatar g0dil
Browse files

HowTos/NewPacket: Remove old code from example

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
parent 5ddb27d2
No related branches found
No related tags found
No related merge requests found
......@@ -116,6 +116,15 @@ prefix_ void senf::console::DirectoryNode::v_help(std::ostream & output)
output << doc_ << "\n";
}
///////////////////////////////////////////////////////////////////////////
// senf::console::SyntaxErrorException
prefix_ char const * senf::console::SyntaxErrorException::what()
const throw()
{
return message().empty() ? "syntax error" : message().c_str();
}
///////////////////////////////////////////////////////////////////////////
// senf::console::SimpleCommandNode
......@@ -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"
......
......@@ -139,6 +139,13 @@ prefix_ senf::console::DirectoryNode::cptr senf::console::DirectoryNode::thisptr
return boost::static_pointer_cast<DirectoryNode const>(shared_from_this());
}
///////////////////////////////////////////////////////////////////////////
// senf::console::SyntaxErrorException
prefix_ senf::console::SyntaxErrorException::SyntaxErrorException(std::string const & msg)
: Exception(msg)
{}
///////////////////////////////////////////////////////////////////////////
// senf::console::CommandNode
......@@ -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_
......
......@@ -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)
{
......@@ -178,11 +178,11 @@
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_;
......
// $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"
// 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:
// $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_
// 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:
// $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
// 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:
......@@ -21,14 +21,14 @@
// 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>
......@@ -37,31 +37,41 @@
///////////////////////////////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////////////////////////////////////////
......
// $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_
// 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:
......@@ -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_
......
......@@ -21,26 +21,26 @@
// 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
......
// $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_
// 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:
......@@ -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)
......
......@@ -805,9 +805,6 @@
(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;
......
......@@ -513,7 +513,7 @@ p.commalist {
}
#autotoc {
width: 20em;
width: 30em;
background-color: #F5F5F5;
border: 1px solid #CCC;
padding: 0 1em;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment