From: g0dil Date: Wed, 26 Mar 2008 00:02:20 +0000 (+0000) Subject: Console: Implement ObjectDirectory proxy X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=9c0078ac0054789badff2a987364ed0448b080ef;p=senf.git Console: Implement ObjectDirectory proxy Console: Implement simple online help Console: Remove uniquify flag Console: Implement node-active check Console: Implement node removal Console: Move 'name' argument consistently to 'add' command Console: Implement SimpleCommandNode (command with manual argument parsing) Console: Implement 'add' family of members based on extensible creation helpers git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@765 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Console/Executor.cc b/Console/Executor.cc index 7e16765..b808a09 100644 --- a/Console/Executor.cc +++ b/Console/Executor.cc @@ -51,9 +51,7 @@ prefix_ bool senf::console::Executor::operator()(ParseCommandInfo const & comman { SENF_LOG(( "Executing: " << command )); - ///\fixme Whenever checking cwd_.expired(), we also need to check, wether - /// the node is still connected to the root. - if (cwd_.expired()) + if (cwd_.expired() || ! cwd().active()) cwd_ = root().thisptr(); try { @@ -66,7 +64,7 @@ prefix_ bool senf::console::Executor::operator()(ParseCommandInfo const & comman if ( command.arguments() ) { if (command.arguments().begin()->size() == 1 && command.arguments().begin()->begin()->value() == "-") { - if (oldCwd_.expired()) { + if (oldCwd_.expired() || ! oldCwd_.lock()->active()) { oldCwd_ = cwd_; cwd_ = root().thisptr(); } else @@ -107,6 +105,23 @@ prefix_ bool senf::console::Executor::operator()(ParseCommandInfo const & comman case ParseCommandInfo::BuiltinEXIT : throw ExitException(); + + case ParseCommandInfo::BuiltinHELP : + try { + GenericNode & node ( + command.arguments() + ? cwd().traverse( + boost::make_iterator_range( + boost::make_transform_iterator(command.arguments().begin()[0].begin(), TraverseTokens()), + boost::make_transform_iterator(command.arguments().begin()[0].end(), TraverseTokens()))) + : cwd() ); + node.help(output); + output << std::flush; + } + catch (UnknownNodeNameException &) { + output << "invalid path" << std::endl; + } + break; } } catch (InvalidDirectoryException &) { diff --git a/Console/Node.cc b/Console/Node.cc index 382804f..f21ab66 100644 --- a/Console/Node.cc +++ b/Console/Node.cc @@ -34,7 +34,7 @@ prefix_ senf::console::DirectoryNode & senf::console::root() { - static DirectoryNode::ptr rootNode(new DirectoryNode("")); + static DirectoryNode::ptr rootNode(new DirectoryNode()); return *rootNode; } @@ -53,15 +53,33 @@ prefix_ std::string senf::console::GenericNode::path() return path.empty() ? "/" : path; } +prefix_ bool senf::console::GenericNode::active() + const +{ + cptr node (thisptr()); + while (node->parent()) + node = node->parent(); + return node == root().thisptr(); +} + /////////////////////////////////////////////////////////////////////////// //senf::console::DirectoryNode -prefix_ void senf::console::DirectoryNode::add(GenericNode::ptr node, bool uniquify) +prefix_ senf::console::GenericNode::ptr +senf::console::DirectoryNode::remove(std::string const & name) +{ + ChildMap::iterator i (children_.find(name)); + if (i == children_.end()) + throw UnknownNodeNameException() << ": '" << name << "'"; + GenericNode::ptr node (i->second); + children_.erase(i); + return node; +} + +prefix_ void senf::console::DirectoryNode::add(GenericNode::ptr node) { BOOST_ASSERT( ! node->parent() ); if (children_.find(node->name()) != children_.end()) { - if (! uniquify) - throw DuplicateNodeNameException() << ": '" << node->name() << "'"; unsigned suffix (0); std::string newName; do { @@ -84,6 +102,21 @@ senf::console::DirectoryNode::get(std::string const & name) return *(i->second); } +prefix_ void senf::console::DirectoryNode::v_help(std::ostream & output) + const +{ + output << doc_ << "\n"; +} + +/////////////////////////////////////////////////////////////////////////// +// senf::console::SimpleCommandNode + +prefix_ void senf::console::SimpleCommandNode::v_help(std::ostream & output) + const +{ + output << doc_ << "\n"; +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ //#include "Node.mpp" diff --git a/Console/Node.cci b/Console/Node.cci index f4fbc11..915d954 100644 --- a/Console/Node.cci +++ b/Console/Node.cci @@ -43,11 +43,9 @@ prefix_ std::string const & senf::console::GenericNode::name() return name_; } -prefix_ senf::console::GenericNode::GenericNode(std::string const & name) - : name_ (name), parent_ (0) -{ - ///\fixme Provide a default name if 'name' is empty ? -} +prefix_ senf::console::GenericNode::GenericNode() + : parent_ (0) +{} prefix_ void senf::console::GenericNode::name(std::string const & name) { @@ -66,6 +64,18 @@ prefix_ boost::shared_ptr senf::console::GenericNo parent_ ? parent_->shared_from_this() : ptr() ); } +prefix_ senf::console::GenericNode::ptr senf::console::GenericNode::unlink() +{ + SENF_ASSERT( parent() ); + return parent()->remove(name()); +} + +prefix_ void senf::console::GenericNode::help(std::ostream & output) + const +{ + v_help(output); +} + prefix_ senf::console::GenericNode::ptr senf::console::GenericNode::thisptr() { return shared_from_this(); @@ -80,12 +90,10 @@ prefix_ senf::console::GenericNode::cptr senf::console::GenericNode::thisptr() /////////////////////////////////////////////////////////////////////////// // senf::console::DirectoryNode -prefix_ senf::console::GenericNode & -senf::console::DirectoryNode::add(std::auto_ptr node, bool uniquify) +prefix_ std::auto_ptr +senf::console::DirectoryNode::create() { - GenericNode::ptr p (node.release()); - add(p, uniquify); - return *p; + return std::auto_ptr(new DirectoryNode()); } prefix_ senf::console::DirectoryNode & @@ -105,8 +113,8 @@ senf::console::DirectoryNode::operator()(std::string const & name) prefix_ senf::console::DirectoryNode & senf::console::DirectoryNode::mkdir(std::string const & name) { - return static_cast( - add(std::auto_ptr(new DirectoryNode(name)))); + std::auto_ptr node (create()); + return add(name, node); } prefix_ senf::console::DirectoryNode::ChildrenRange senf::console::DirectoryNode::children() @@ -115,10 +123,16 @@ prefix_ senf::console::DirectoryNode::ChildrenRange senf::console::DirectoryNode return boost::make_iterator_range(children_.begin(), children_.end()); } -prefix_ senf::console::DirectoryNode::DirectoryNode(std::string const & name) - : GenericNode(name) +prefix_ senf::console::DirectoryNode::DirectoryNode() {} +prefix_ senf::console::DirectoryNode & +senf::console::DirectoryNode::doc(std::string const & doc) +{ + doc_ = doc; + return *this; +} + prefix_ senf::console::DirectoryNode::ptr senf::console::DirectoryNode::thisptr() { return boost::static_pointer_cast(shared_from_this()); @@ -133,10 +147,6 @@ prefix_ senf::console::DirectoryNode::cptr senf::console::DirectoryNode::thisptr /////////////////////////////////////////////////////////////////////////// // senf::console::CommandNode -prefix_ senf::console::CommandNode::CommandNode(std::string const & name) - : GenericNode(name) -{} - prefix_ senf::console::CommandNode::ptr senf::console::CommandNode::thisptr() { return boost::static_pointer_cast(shared_from_this()); @@ -148,6 +158,35 @@ prefix_ senf::console::CommandNode::cptr senf::console::CommandNode::thisptr() return boost::static_pointer_cast(shared_from_this()); } +prefix_ senf::console::CommandNode::CommandNode() +{} + +/////////////////////////////////////////////////////////////////////////// +// senf::console::SimpleCommandNode + +prefix_ void senf::console::SimpleCommandNode::operator()(std::ostream & output, + Arguments const & arguments) +{ + fn_(output, arguments); +} + +prefix_ senf::console::SimpleCommandNode::SimpleCommandNode(Function const & fn) + : fn_ (fn) +{} + +prefix_ std::auto_ptr +senf::console::SimpleCommandNode::create(Function const & fn) +{ + return std::auto_ptr(new SimpleCommandNode(fn)); +} + +prefix_ senf::console::SimpleCommandNode & +senf::console::SimpleCommandNode::doc(std::string const & doc) +{ + doc_ = doc; + return *this; +} + ///////////////////////////////cci.e/////////////////////////////////////// #undef prefix_ diff --git a/Console/Node.cti b/Console/Node.cti new file mode 100644 index 0000000..c56f014 --- /dev/null +++ b/Console/Node.cti @@ -0,0 +1,97 @@ +// $Id$ +// +// Copyright (C) 2008 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// 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 Node inline template implementation */ + +//#include "Node.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::console::NodeCreateTraits::Creator + +template +prefix_ typename senf::console::NodeCreateTraits::NodeType & +senf::console::NodeCreateTraits::Creator::create(DirectoryNode & node, + std::string const & name, + Object const & ob) +{ + return senf_console_add_node(node, name, ob, 0); +} + +/////////////////////////////////////////////////////////////////////////// +// senf::console::DirectoryNode + +template +prefix_ NodeType & senf::console::DirectoryNode::add(std::string const & name, + std::auto_ptr node) +{ + GenericNode::ptr p (node); + p->name(name); + add(p); + return static_cast(*p); +} + +template +prefix_ NodeType & senf::console::DirectoryNode::add(std::string const & name, + boost::shared_ptr node) +{ + SENF_ASSERT( ! node->parent() ); + node->name(name); + add(node); + return *node; +} + +template +prefix_ typename senf::console::NodeCreateTraits::NodeType & +senf::console::DirectoryNode::add(std::string const & name, Object const & ob) +{ + return NodeCreateTraits::Creator::create(*this, name, ob); +} + +/////////////////////////////////////////////////////////////////////////// +// senf::console::SimpleCommandNode + +template +prefix_ senf::console::SimpleCommandNode & senf::console:: +senf_console_add_node(DirectoryNode & node, std::string const & name, Function const & fn, ...) +{ + return node.add(name, SimpleCommandNode::create(fn)); +} + +///////////////////////////////cti.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: diff --git a/Console/Node.hh b/Console/Node.hh index d081ffd..10ac02e 100644 --- a/Console/Node.hh +++ b/Console/Node.hh @@ -33,12 +33,17 @@ #include #include #include +#include +#include #include "../Utils/Exception.hh" +#include "../Utils/mpl.hh" #include "Parse.hh" //#include "Node.mpp" ///////////////////////////////hh.p//////////////////////////////////////// +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() + namespace senf { namespace console { @@ -64,21 +69,28 @@ namespace console { std::string const & name() const; boost::shared_ptr parent() const; - bool managed() const; std::string path() const; + ptr unlink(); + + bool active() const; + + void help(std::ostream & output) const; + ptr thisptr(); cptr thisptr() const; protected: - explicit GenericNode(std::string const & name); + GenericNode(); void name(std::string const & name); static void name(GenericNode & node, std::string const & name); void parent(DirectoryNode * parent); private: + virtual void v_help(std::ostream & output) const = 0; + std::string name_; DirectoryNode * parent_; @@ -86,7 +98,27 @@ namespace console { friend class DirectoryNode; }; + class SimpleCommandNode; + + template + struct NodeCreateTraits + { + typedef BOOST_TYPEOF_TPL( senf_console_add_node( + * static_cast(0), + * static_cast(0), + * static_cast(0), + 0) ) result_type; + + typedef typename boost::remove_reference::type NodeType; + + struct Creator { + static NodeType & create(DirectoryNode & node, std::string const & name, + Object const & ob); + }; + }; + /** \brief + ///\fixme Provide a default name for added nodes if 'name' is empty ? */ class DirectoryNode : public GenericNode { @@ -104,8 +136,27 @@ namespace console { typedef ChildMap::const_iterator child_iterator; /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///\{ + + static std::auto_ptr create(); + + ///\} + /////////////////////////////////////////////////////////////////////////// + ///\name Children + ///\{ + + template + NodeType & add(std::string const & name, std::auto_ptr node); + + template + NodeType & add(std::string const & name, boost::shared_ptr node); - GenericNode & add(std::auto_ptr node, bool uniquify = true); + template + typename NodeCreateTraits::NodeType & add (std::string const & name, + Object const & ob); + + GenericNode::ptr remove(std::string const & name); DirectoryNode & operator[](std::string const & name) const; CommandNode & operator()(std::string const & name) const; @@ -115,29 +166,44 @@ namespace console { ChildrenRange children() const; + ///\} + /////////////////////////////////////////////////////////////////////////// + template GenericNode & traverse(ForwardRange const & range); + DirectoryNode & doc(std::string const & doc); + ptr thisptr(); cptr thisptr() const; protected: - explicit DirectoryNode(std::string const & name); + DirectoryNode(); private: - void add(GenericNode::ptr node, bool uniquify); + void add(GenericNode::ptr node); + virtual void v_help(std::ostream & output) const; ChildMap children_; + std::string doc_; friend DirectoryNode & root(); }; - struct DuplicateNodeNameException : public senf::Exception - { DuplicateNodeNameException() : senf::Exception("Duplicate node name") {}}; + BOOST_TYPEOF_REGISTER_TYPE(DirectoryNode); struct UnknownNodeNameException : public senf::Exception { UnknownNodeNameException() : senf::Exception("Unknown node name") {}}; + // We need this specialization since we cannot passe auto_ptr via const & !! + template + struct NodeCreateTraits< std::auto_ptr > + {}; + + template + struct NodeCreateTraits< boost::shared_ptr > + {}; + /** \brief */ class CommandNode : public GenericNode @@ -150,21 +216,58 @@ namespace console { typedef boost::shared_ptr cptr; typedef boost::weak_ptr weak_ptr; + typedef ParseCommandInfo::ArgumentsRange Arguments; + + /////////////////////////////////////////////////////////////////////////// + + virtual void operator()(std::ostream & output, Arguments const & arguments) = 0; + + ptr thisptr(); + cptr thisptr() const; + + protected: + CommandNode(); + + private: + }; + + /** \brief + */ + class SimpleCommandNode : public CommandNode + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef boost::function Function; + /////////////////////////////////////////////////////////////////////////// - virtual void operator()(std::ostream & output, - ParseCommandInfo::ArgumentsRange const & arguments) = 0; + virtual void operator()(std::ostream & output, Arguments const & arguments); ptr thisptr(); cptr thisptr() const; + static std::auto_ptr create(Function const & fn); + + SimpleCommandNode & doc(std::string const & doc); + protected: - explicit CommandNode(std::string const & name); + SimpleCommandNode(Function const & fn); private: + virtual void v_help(std::ostream & output) const; + Function fn_; + std::string doc_; }; + template + SimpleCommandNode & senf_console_add_node(DirectoryNode & node, std::string const & name, + Function const & fn, ...); + + BOOST_TYPEOF_REGISTER_TYPE(SimpleCommandNode); + DirectoryNode & root(); }} @@ -172,7 +275,7 @@ namespace console { ///////////////////////////////hh.e//////////////////////////////////////// #include "Node.cci" #include "Node.ct" -//#include "Node.cti" +#include "Node.cti" #endif diff --git a/Console/ObjectDirectory.cti b/Console/ObjectDirectory.cti new file mode 100644 index 0000000..3fb3a62 --- /dev/null +++ b/Console/ObjectDirectory.cti @@ -0,0 +1,113 @@ +// $Id$ +// +// Copyright (C) 2008 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// 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 ObjectDirectory inline template implementation */ + +//#include "ObjectDirectory.ih" + +// Custom includes +#include + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::console::OwnerNodeCreateTraits::Creator + +template +prefix_ typename senf::console::OwnerNodeCreateTraits::NodeType & +senf::console::OwnerNodeCreateTraits::Creator::create(DirectoryNode & node, + Owner & owner, + std::string const & name, + Object const & ob) +{ + return senf_console_add_node(node, owner, name, ob); +} + +/////////////////////////////////////////////////////////////////////////// +// senf::console::ObjectDirectory + +template +prefix_ senf::console::ObjectDirectory::ObjectDirectory(Owner * owner) + : node_ (DirectoryNode::create().release()), owner_ (owner) +{} + +template +prefix_ senf::console::ObjectDirectory::~ObjectDirectory() +{ + node_->unlink(); +} + +template +template +prefix_ typename senf::console::OwnerNodeCreateTraits::NodeType & +senf::console::ObjectDirectory::add(std::string const & name, Object const & ob) +{ + return OwnerNodeCreateTraits::Creator::create(*node_, *owner_, name, ob); +} + +template +prefix_ senf::console::DirectoryNode & senf::console::ObjectDirectory::node() + const +{ + return *node_; +} + +template +prefix_ senf::console::SimpleCommandNode & senf::console:: +senf_console_add_node(DirectoryNode & node, Owner & , std::string const & name, + Function const & fn) +{ + return node.add(name,fn); +} + +template +prefix_ senf::console::SimpleCommandNode & senf::console:: +senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name, + void (Owner::*fn)(std::ostream & output, + CommandNode::Arguments const & arguments)) +{ + return node.add(name, boost::bind(fn,boost::ref(owner),_1,_2)); +} + +template +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 >::type *) +{ + return dir.add(name, node.node().thisptr()); +} + +///////////////////////////////cti.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: diff --git a/Console/ObjectDirectory.hh b/Console/ObjectDirectory.hh new file mode 100644 index 0000000..ccecf8d --- /dev/null +++ b/Console/ObjectDirectory.hh @@ -0,0 +1,127 @@ +// $Id$ +// +// Copyright (C) 2008 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// 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 ObjectDirectory public header */ + +#ifndef HH_ObjectDirectory_ +#define HH_ObjectDirectory_ 1 + +// Custom includes +#include +#include +#include "Node.hh" + +//#include "ObjectDirectory.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { +namespace console { + + template + struct OwnerNodeCreateTraits + { + typedef BOOST_TYPEOF_TPL( senf_console_add_node( + * static_cast(0), + * static_cast(0), + * static_cast(0), + * static_cast(0)) ) result_type; + + typedef typename boost::remove_reference::type NodeType; + + struct Creator { + static NodeType & create(DirectoryNode & node, Owner & owner, + std::string const & name, Object const & ob); + }; + }; + + struct ObjectDirectoryBase {}; + + /** \brief + */ + template + class ObjectDirectory : public ObjectDirectoryBase + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef Owner owner; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + ObjectDirectory(Owner * owner); + ~ObjectDirectory(); + + ///@} + /////////////////////////////////////////////////////////////////////////// + + template + typename OwnerNodeCreateTraits::NodeType & add(std::string const & name, + Object const & ob); + + DirectoryNode & node() const; + + protected: + + private: + static SimpleCommandNode & create(DirectoryNode & node, Owner * owner, + std::string const & name, + SimpleCommandNode::Function const & fn); + + DirectoryNode::ptr node_; + Owner * owner_; + }; + + template + SimpleCommandNode & senf_console_add_node( + DirectoryNode & node, Owner & owner, std::string const & name, Function const & fn); + + template + SimpleCommandNode & senf_console_add_node( + DirectoryNode & node, Owner & owner, std::string const & name, + void (Owner::*fn)(std::ostream & output, CommandNode::Arguments const & arguments)); + + template + DirectoryNode & senf_console_add_node( + DirectoryNode & dir, std::string const & name, Node const & node, int, + typename boost::enable_if< boost::is_convertible >::type * = 0); +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "ObjectDirectory.cci" +//#include "ObjectDirectory.ct" +#include "ObjectDirectory.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: diff --git a/Console/ObjectDirectory.test.cc b/Console/ObjectDirectory.test.cc new file mode 100644 index 0000000..1c5ac82 --- /dev/null +++ b/Console/ObjectDirectory.test.cc @@ -0,0 +1,53 @@ +// $Id$ +// +// Copyright (C) 2008 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// 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 ObjectDirectory.test unit tests */ + +//#include "ObjectDirectory.test.hh" +//#include "ObjectDirectory.test.ih" + +// Custom includes +#include "ObjectDirectory.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +BOOST_AUTO_UNIT_TEST(ownerDirectory) +{} + +///////////////////////////////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: diff --git a/Console/Parse.cc b/Console/Parse.cc index a631f0f..bf49f31 100644 --- a/Console/Parse.cc +++ b/Console/Parse.cc @@ -133,6 +133,12 @@ namespace detail { ParserAccess::setBuiltin(info_, ParseCommandInfo::BuiltinEXIT); ParserAccess::finalize(info_); cb_(info_); } + void builtin_help(std::vector & path) + { ParserAccess::init(info_); + ParserAccess::setBuiltin(info_, ParseCommandInfo::BuiltinHELP); + setBuiltinPathArg(path); + ParserAccess::finalize(info_); cb_(info_); } + void setBuiltinPathArg(std::vector & path) { ParserAccess::startArgument(info_); @@ -181,7 +187,7 @@ prefix_ std::ostream & senf::console::operator<<(std::ostream & stream, if (info.builtin() == ParseCommandInfo::NoBuiltin) stream << senf::stringJoin(info.commandPath(), "/"); else { - char const * builtins[] = { "", "cd", "ls", "pushd", "popd", "exit" }; + char const * builtins[] = { "", "cd", "ls", "pushd", "popd", "exit", "help" }; stream << "builtin-" << builtins[info.builtin()]; } diff --git a/Console/Parse.hh b/Console/Parse.hh index a4e452c..36cde7c 100644 --- a/Console/Parse.hh +++ b/Console/Parse.hh @@ -89,7 +89,8 @@ namespace console { BuiltinLS, BuiltinPUSHD, BuiltinPOPD, - BuiltinEXIT }; + BuiltinEXIT, + BuiltinHELP }; BuiltinCommand builtin() const; CommandPathRange commandPath() const; diff --git a/Console/Parse.ih b/Console/Parse.ih index 9f7edf9..02930e6 100644 --- a/Console/Parse.ih +++ b/Console/Parse.ih @@ -208,11 +208,16 @@ namespace detail { >> path >> eps_p [ self.dispatch(&PD::builtin_cd, boost::ref(self.context.path)) ] - | keyword_p("ls") + | keyword_p("ls") >> ! path >> eps_p [ self.dispatch(&PD::builtin_ls, boost::ref(self.context.path)) ] | keyword_p("exit") [ self.dispatch(&PD::builtin_exit) ] + + | keyword_p("help") + >> ! path + >> eps_p [ self.dispatch(&PD::builtin_help, + boost::ref(self.context.path)) ] ; block diff --git a/Console/Parse.test.cc b/Console/Parse.test.cc index 3f83d57..8c03817 100644 --- a/Console/Parse.test.cc +++ b/Console/Parse.test.cc @@ -78,6 +78,8 @@ namespace { os_ << "builtin_cd( " << senf::stringJoin(path, "/") << " )\n"; } void builtin_exit() { os_ << "builtin_exit()\n"; } + void builtin_help(std::vector const & path) + { os_ << "builtin_help( " << senf::stringJoin(path, "/") << " )\n"; } }; } diff --git a/Console/Server.cc b/Console/Server.cc index 72fd25c..4e37e68 100644 --- a/Console/Server.cc +++ b/Console/Server.cc @@ -126,11 +126,6 @@ prefix_ void senf::console::Client::clientData(ReadHelper::ptr hel return; } - ///\fixme Fix Client::clientData implementation - /// Remove the 'dup' needed here so we don't close the same fd twice (see Client constructor) - /// Make output non-blocking - /// Don't register a new ReadHelper every round - std::string data (tail_ + helper->data()); tail_ = helper->tail(); boost::trim(data); // Gets rid of superfluous \r or \n characters diff --git a/Console/Server.hh b/Console/Server.hh index bfce303..c8d2c7f 100644 --- a/Console/Server.hh +++ b/Console/Server.hh @@ -51,6 +51,7 @@ namespace console { class Client; /** \brief + ///\fixme Use special non-blocking streambuf */ class Server : boost::noncopyable @@ -94,6 +95,11 @@ namespace console { }; /** \brief + + \fixme Fix Client::clientData implementation + Remove the 'dup' needed here so we don't close the same fd twice (see Client constructor) + Make output non-blocking + Don't register a new ReadHelper every round */ class Client : public senf::intrusive_refcount diff --git a/Console/testServer.cc b/Console/testServer.cc index b55ca1b..f0d500e 100644 --- a/Console/testServer.cc +++ b/Console/testServer.cc @@ -30,6 +30,7 @@ #include #include "Server.hh" #include "Node.hh" +#include "ObjectDirectory.hh" #include "../Scheduler/Scheduler.hh" #include "../Utils/Logger/SenfLog.hh" @@ -38,33 +39,52 @@ ///////////////////////////////cc.p//////////////////////////////////////// namespace { - struct MyCommand : public senf::console::CommandNode + + void fn(std::ostream & output, + senf::console::CommandNode::Arguments const & arguments) { + senf::console::CommandNode::Arguments::iterator i (arguments.begin()); + senf::console::CommandNode::Arguments::iterator i_end (arguments.end()); + for (; i != i_end; ++i) { + senf::console::CommandNode::Arguments::value_type::iterator j (i->begin()); + senf::console::CommandNode::Arguments::value_type::iterator j_end (i->end()); + for (; j != j_end; ++j) + output << j->value() << ' '; + } + output << "\n"; + } + + struct TestObject { - MyCommand(std::string name) : senf::console::CommandNode(name) {} - void operator()(std::ostream & output, - senf::console::ParseCommandInfo::ArgumentsRange const & arguments) { - senf::console::ParseCommandInfo::argument_iterator i (arguments.begin()); - senf::console::ParseCommandInfo::argument_iterator i_end (arguments.end()); - for (; i != i_end; ++i) { - senf::console::ParseCommandInfo::token_iterator j (i->begin()); - senf::console::ParseCommandInfo::token_iterator j_end (i->end()); - for (; j != j_end; ++j) - output << j->value() << ' '; - } - output << "\n"; + senf::console::ObjectDirectory dir; + + TestObject() : dir(this) { + dir.add("blub", &TestObject::blub) + .doc("Example of a member function"); + } + + void blub(std::ostream & output, senf::console::CommandNode::Arguments const & args) { + output << "blub\n"; } }; + } int main(int, char const **) { senf::log::ConsoleTarget::instance().route< senf::SenfLog, senf::log::NOTICE >(); - senf::console::root().mkdir("network").mkdir("eth0"); + senf::console::root().doc("This is the console test application"); + senf::console::root().mkdir("network") + .doc("Network related settings"); + senf::console::root()["network"].mkdir("eth0") + .doc("Ethernet device eth0"); senf::console::root().mkdir("server"); + senf::console::root()["network"].add("route", &fn) + .doc("Example of a directly registered function"); - senf::console::root()["network"].add( - std::auto_ptr(new MyCommand("route"))); + TestObject test; + senf::console::root().add("testob", test.dir) + .doc("Example of an instance directory"); senf::console::Server::start( senf::INet4SocketAddress("127.0.0.1:23232") ) .name("testServer");