#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
+namespace {
+
+ struct TraverseTokens {
+ typedef std::string const & result_type;
+ result_type operator()(senf::console::ArgumentToken const & token) const {
+ return token.value();
+ }
+ };
+
+}
+
///////////////////////////////////////////////////////////////////////////
// senf::console::Executor
{
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())
- cwd_ = boost::static_pointer_cast<DirectoryNode>(
- root().shared_from_this());
-
- switch(command.builtin()) {
- case ParseCommandInfo::NoBuiltin :
- break;
+ cwd_ = root().thisptr();
- case ParseCommandInfo::BuiltinCD :
- if ( command.arguments() &&
- ! chdir(command.arguments().begin()[0]) )
- output << "invalid directory\n";
- break;
-
- case ParseCommandInfo::BuiltinLS :
- for (DirectoryNode::child_iterator i (cwd().children().begin());
- i != cwd().children().end(); ++i) {
- output << i->first;
- try {
- (void) cwd()(i->first);
+ try {
+ switch(command.builtin()) {
+ case ParseCommandInfo::NoBuiltin :
+ break;
+
+ case ParseCommandInfo::BuiltinCD :
+ if ( command.arguments() ) {
+ if (command.arguments().begin()->size() == 1
+ && command.arguments().begin()->begin()->value() == "-") {
+ if (oldCwd_.expired()) {
+ oldCwd_ = cwd_;
+ cwd_ = root().thisptr();
+ } else
+ swap(cwd_, oldCwd_);
+ }
+ else {
+ oldCwd_ = cwd_;
+ cwd_ = traverseTo(command.arguments().begin()[0]).thisptr();
+ }
}
- catch (std::bad_cast &) {
- output << "/";
+ break;
+
+ case ParseCommandInfo::BuiltinLS : {
+ DirectoryNode const & dir (
+ command.arguments().empty() ? cwd() : traverseTo(command.arguments().begin()[0]));
+ for (DirectoryNode::child_iterator i (dir.children().begin());
+ i != dir.children().end(); ++i) {
+ output << i->first;
+ if (boost::dynamic_pointer_cast<DirectoryNode>(i->second))
+ output << "/";
+ output << "\n";
}
- output << "\n";
+ break;
}
- break;
- case ParseCommandInfo::BuiltinPUSHD :
- dirstack_.push_back(cwd_);
- if ( command.arguments()
- && ! chdir(command.arguments().begin()[0]) )
- output << "invalid directory\n";
- break;
-
- case ParseCommandInfo::BuiltinPOPD :
- if (! dirstack_.empty()) {
- cwd_ = dirstack_.back();
- dirstack_.pop_back();
+ case ParseCommandInfo::BuiltinPUSHD :
+ dirstack_.push_back(cwd_);
+ if ( command.arguments() )
+ cwd_ = traverseTo(command.arguments().begin()[0]).thisptr();
+ break;
+
+ case ParseCommandInfo::BuiltinPOPD :
+ if (! dirstack_.empty()) {
+ cwd_ = dirstack_.back();
+ dirstack_.pop_back();
+ }
+ break;
+
+ case ParseCommandInfo::BuiltinEXIT :
+ throw ExitException();
}
- break;
-
- case ParseCommandInfo::BuiltinEXIT :
- throw ExitException();
+ }
+ catch (InvalidDirectoryException &) {
+ output << "invalid directory" << std::endl;
}
return true;
}
-prefix_ bool senf::console::Executor::chdir(ParseCommandInfo::argument_value_type const & path)
+prefix_ senf::console::DirectoryNode &
+senf::console::Executor::traverseTo(ParseCommandInfo::argument_value_type const & path)
{
- if (path.size() == 1 && path.begin()->value() == "-") {
- if (oldCwd_.expired()) {
- oldCwd_ = cwd_;
- cwd_ = boost::static_pointer_cast<DirectoryNode>(
- root().shared_from_this());
- } else
- swap(cwd_, oldCwd_);
+ try {
+ return dynamic_cast<DirectoryNode&>(
+ cwd().traverse(
+ boost::make_iterator_range(
+ boost::make_transform_iterator(path.begin(), TraverseTokens()),
+ boost::make_transform_iterator(path.end(), TraverseTokens()))));
}
- else {
- try {
- DirectoryNode::ptr dir (cwd_.lock());
- ParseCommandInfo::token_iterator i (path.begin());
- ParseCommandInfo::token_iterator const i_end (path.end());
- if (i != i_end && i->value().empty()) {
- dir = boost::static_pointer_cast<DirectoryNode>(
- root().shared_from_this());
- ++ i;
- }
- for (; i != i_end; ++i) {
- if (i->value() == "..") {
- dir = dir->parent();
- if (! dir)
- dir = boost::static_pointer_cast<DirectoryNode>(
- root().shared_from_this());
- }
- else if (! i->value().empty() && i->value() != ".")
- dir = boost::static_pointer_cast<DirectoryNode>(
- (*dir)[i->value()].shared_from_this());
- }
- oldCwd_ = cwd_;
- cwd_ = dir;
- }
- catch (std::bad_cast &) {
- return false;
- }
- catch (UnknownNodeNameException &) {
- return false;
- }
+ catch (std::bad_cast &) {
+ throw InvalidDirectoryException();
+ }
+ catch (UnknownNodeNameException &) {
+ throw InvalidDirectoryException();
}
- return true;
}
///////////////////////////////cc.e////////////////////////////////////////
protected:
private:
- bool chdir(ParseCommandInfo::argument_value_type const & path);
+ DirectoryNode & traverseTo(ParseCommandInfo::argument_value_type const & path);
+
+ struct InvalidDirectoryException {};
DirectoryNode::weak_ptr cwd_;
DirectoryNode::weak_ptr oldCwd_;
}
prefix_ senf::console::GenericNode &
-senf::console::DirectoryNode::lookup(std::string const & name)
+senf::console::DirectoryNode::get(std::string const & name)
const
{
ChildMap::const_iterator i (children_.find(name));
prefix_ senf::console::GenericNode::GenericNode(std::string const & name)
: name_ (name), parent_ (0)
-{}
+{
+ ///\fixme Provide a default name if 'name' is empty ?
+}
prefix_ void senf::console::GenericNode::name(std::string const & name)
{
parent_ ? parent_->shared_from_this() : ptr() );
}
+prefix_ senf::console::GenericNode::ptr senf::console::GenericNode::thisptr()
+{
+ return shared_from_this();
+}
+
+prefix_ senf::console::GenericNode::cptr senf::console::GenericNode::thisptr()
+ const
+{
+ return shared_from_this();
+}
+
///////////////////////////////////////////////////////////////////////////
// senf::console::DirectoryNode
senf::console::DirectoryNode::operator[](std::string const & name)
const
{
- return dynamic_cast<DirectoryNode&>(lookup(name));
+ return dynamic_cast<DirectoryNode&>(get(name));
}
prefix_ senf::console::CommandNode &
senf::console::DirectoryNode::operator()(std::string const & name)
const
{
- return dynamic_cast<CommandNode&>(lookup(name));
+ return dynamic_cast<CommandNode&>(get(name));
}
prefix_ senf::console::DirectoryNode &
: GenericNode(name)
{}
+prefix_ senf::console::DirectoryNode::ptr senf::console::DirectoryNode::thisptr()
+{
+ return boost::static_pointer_cast<DirectoryNode>(shared_from_this());
+}
+
+prefix_ senf::console::DirectoryNode::cptr senf::console::DirectoryNode::thisptr()
+ const
+{
+ return boost::static_pointer_cast<DirectoryNode const>(shared_from_this());
+}
+
///////////////////////////////////////////////////////////////////////////
// senf::console::CommandNode
: GenericNode(name)
{}
+prefix_ senf::console::CommandNode::ptr senf::console::CommandNode::thisptr()
+{
+ return boost::static_pointer_cast<CommandNode>(shared_from_this());
+}
+
+prefix_ senf::console::CommandNode::cptr senf::console::CommandNode::thisptr()
+ const
+{
+ return boost::static_pointer_cast<CommandNode const>(shared_from_this());
+}
+
///////////////////////////////cci.e///////////////////////////////////////
#undef prefix_
--- /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 Node non-inline template implementation */
+
+//#include "Node.ih"
+
+// Custom includes
+#include <boost/range.hpp>
+
+#define prefix_
+///////////////////////////////ct.p////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::DirectoryNode
+
+template <class ForwardRange>
+prefix_ senf::console::GenericNode &
+senf::console::DirectoryNode::traverse(ForwardRange const & range)
+{
+ typedef typename boost::range_const_iterator<ForwardRange>::type const_iterator;
+ DirectoryNode::ptr dir (thisptr());
+ const_iterator i (boost::begin(range));
+ const_iterator const i_end (boost::end(range));
+ if (i != i_end && i->empty()) {
+ dir = root().thisptr();
+ ++ i;
+ }
+ while (i != i_end) {
+ const_iterator next_i (i);
+ ++ next_i;
+ if (*i == "..") {
+ dir = dir->parent();
+ if (! dir)
+ dir = root().thisptr();
+ }
+ else if (! i->empty() && *i != ".") {
+ if (next_i == i_end)
+ return dir->get(*i);
+ else {
+ // Why does g++ give an error on this line ???? :
+ // dir = dynamic_cast<DirectoryNode&>( dir->get(*i) ).thisptr();
+ DirectoryNode & d (dynamic_cast<DirectoryNode&>( dir->get(*i) ));
+ dir = d.thisptr();
+ }
+ }
+ i = next_i;
+ }
+ return *dir;
+}
+
+///////////////////////////////ct.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:
// Types
typedef boost::shared_ptr<GenericNode> ptr;
+ typedef boost::shared_ptr<GenericNode const> cptr;
typedef boost::weak_ptr<GenericNode> weak_ptr;
///////////////////////////////////////////////////////////////////////////
std::string path() const;
+ ptr thisptr();
+ cptr thisptr() const;
+
protected:
explicit GenericNode(std::string const & name);
// Types
typedef boost::shared_ptr<DirectoryNode> ptr;
+ typedef boost::shared_ptr<DirectoryNode const> cptr;
typedef boost::weak_ptr<DirectoryNode> weak_ptr;
typedef boost::iterator_range<ChildMap::const_iterator> ChildrenRange;
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);
ChildrenRange children() const;
+ template <class ForwardRange>
+ GenericNode & traverse(ForwardRange const & range);
+
+ ptr thisptr();
+ cptr thisptr() const;
+
protected:
explicit DirectoryNode(std::string const & name);
private:
void add(GenericNode::ptr node, bool uniquify);
- GenericNode & lookup(std::string const & name) const;
ChildMap children_;
// Types
typedef boost::shared_ptr<CommandNode> ptr;
+ typedef boost::shared_ptr<CommandNode const> cptr;
typedef boost::weak_ptr<CommandNode> weak_ptr;
///////////////////////////////////////////////////////////////////////////
+ ptr thisptr();
+ cptr thisptr() const;
+
protected:
explicit CommandNode(std::string const & name);
///////////////////////////////hh.e////////////////////////////////////////
#include "Node.cci"
-//#include "Node.ct"
+#include "Node.ct"
//#include "Node.cti"
#endif
abspath
= ch_p('/') [ push_back_a(self.context.path, "") ]
- >> ! ( ( word [ push_back_a(self.context.path) ]
- % ch_p('/') )
- >> ( ! ch_p('/') [ push_back_a(self.context.path,"") ] ) )
+ >> ( relpath
+ | eps_p [ push_back_a(self.context.path, "") ] )
;
balanced_tokens
return;
}
-# warning 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
+ ///\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();