executor_.restrict_ = senf::console::root().thisptr();
}
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::ConfigSource
+
+prefix_ senf::console::detail::ConfigSource::~ConfigSource()
+{}
+
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
//#include "Config.mpp"
///////////////////////////////cci.p///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::RestrictedExecutor
+
+prefix_ bool senf::console::detail::RestrictedExecutor::complete()
+ const
+{
+ return parsedNodes_.size() == 1
+ && ! parsedNodes_[0].expired()
+ && *parsedNodes_[0].lock() == executor_.chroot();
+}
+
+prefix_ void senf::console::detail::RestrictedExecutor::reset()
+{
+ parsedNodes_.clear();
+}
+
+prefix_ senf::console::DirectoryNode & senf::console::detail::RestrictedExecutor::root()
+ const
+{
+ return executor_.chroot();
+}
+
+///////////////////////////////////////////////////////////////////////////
// senf::console::ConfigBundle
prefix_ senf::console::ConfigBundle::ConfigBundle()
: executor_ (root)
{}
-prefix_ void senf::console::ConfigBundle::add(detail::ConfigSource::ptr source)
-{
- sources_.push_back(source);
-}
-
prefix_ bool senf::console::ConfigBundle::complete()
const
{
}
///////////////////////////////////////////////////////////////////////////
-// senf::console::detail::RestrictedExecutor
-
-prefix_ bool senf::console::detail::RestrictedExecutor::complete()
- const
-{
- return parsedNodes_.size() == 1
- && ! parsedNodes_[0].expired()
- && *parsedNodes_[0].lock() == executor_.chroot();
-}
-
-prefix_ void senf::console::detail::RestrictedExecutor::reset()
-{
- parsedNodes_.clear();
-}
-
-prefix_ senf::console::DirectoryNode & senf::console::detail::RestrictedExecutor::root()
- const
-{
- return executor_.chroot();
-}
-
-///////////////////////////////////////////////////////////////////////////
// senf::console::detail::ConfigSource
prefix_ void senf::console::detail::ConfigSource::parse(RestrictedExecutor & executor)
bundle_.reset();
}
-prefix_ void senf::console::detail::BundleMixin::add(ConfigSource::ptr source)
-{
- bundle_.add(source);
-}
-
///////////////////////////////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 Config inline template implementation */
+
+#include "Config.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ConfigBundle
+
+template <class Source>
+prefix_ Source & senf::console::ConfigBundle::add(boost::intrusive_ptr<Source> source)
+{
+ sources_.push_back(source);
+ return *source;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::BundleMixin
+
+template <class Source>
+prefix_ Source & senf::console::detail::BundleMixin::add(boost::intrusive_ptr<Source> source)
+{
+ return bundle_.add(source);
+}
+
+///////////////////////////////cti.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:
///@}
///////////////////////////////////////////////////////////////////////////
- void add(detail::ConfigSource::ptr source);
+ template <class Source>
+ Source & add(boost::intrusive_ptr<Source> source);
void parse(); ///< Parse config file
/**< All nodes already parsed are skipped */
complete config file again. */
protected:
- void add(ConfigSource::ptr source);
-
+ template <class Source>
+ Source & add(boost::intrusive_ptr<Source> source);
+
private:
ConfigBundle bundle_;
};
///////////////////////////////hh.e////////////////////////////////////////
#include "Config.cci"
//#include "Config.ct"
-//#include "Config.cti"
+#include "Config.cti"
#endif
\f
{
public:
typedef boost::intrusive_ptr<ConfigSource> ptr;
+ virtual ~ConfigSource();
void parse(RestrictedExecutor & executor);
--- /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 Config.test unit tests */
+
+//#include "Config.test.hh"
+//#include "Config.test.ih"
+
+// Custom includes
+#include "Config.hh"
+#include "ScopedDirectory.hh"
+#include "ParsedCommand.hh"
+#include "ConfigFile.hh"
+#include "ProgramOptions.hh"
+#include <boost/filesystem/operations.hpp>
+
+#include "../Utils/auto_unit_test.hh"
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+namespace {
+ std::string val1;
+ bool val2 (false);
+
+ void fun1(std::string p)
+ { val1 = p; }
+
+ void fun2()
+ { val2 = true; }
+
+ class TempFile
+ {
+ public:
+ TempFile(std::string const & name) : name_ (name), file_ (name_.c_str()) {}
+ ~TempFile() { file_.close(); boost::filesystem::remove(name_); }
+
+ template <class T> TempFile & operator<<(T const & v) { file_ << v; return *this; }
+ enum Closer { close }; void operator<<(Closer) { file_.close(); }
+ std::string const & name() { return name_; }
+
+ private:
+ std::string name_;
+ std::ofstream file_;
+ };
+}
+
+BOOST_AUTO_UNIT_TEST(configBundle)
+{
+ senf::console::ScopedDirectory<> root;
+ senf::console::root().add("root",root);
+
+ root.mkdir("dir1").add("fun1",&fun1);
+ root.add("fun2",&fun2);
+
+ TempFile cfg ("test.cfg");
+ cfg << "dir1/fun1 foo; fun2;" << TempFile::close;
+
+ char * argv[] = { "", "--dir1-fun1=bar" };
+
+ senf::console::ConfigBundle bundle(root);
+ bundle.add( senf::console::FileConfig(cfg.name()) );
+ bundle.add( senf::console::OptionsConfig(sizeof(argv)/sizeof(argv[0]), argv) );
+
+ SENF_CHECK_NO_THROW( bundle.parse() );
+ BOOST_CHECK_EQUAL( val1, "bar" );
+ BOOST_CHECK_EQUAL( val2, true );
+}
+
+///////////////////////////////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:
class ConfigFileSource : public ConfigSource
{
public:
+ typedef boost::intrusive_ptr<ConfigFileSource> ptr;
+
static ptr create(std::string const & filename);
private:
}
///////////////////////////////////////////////////////////////////////////
-// 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)
///////////////////////////////////////////////////////////////////////////
// senf::console::GenericNode
+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();
+}
+
prefix_ senf::console::GenericNode::~GenericNode()
{}
v_help(output);
}
-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();
-}
-
prefix_ bool senf::console::GenericNode::operator==(GenericNode & other)
const
{
///////////////////////////////////////////////////////////////////////////
// senf::console::LinkNode
+prefix_ senf::console::GenericNode & senf::console::LinkNode::follow()
+ const
+{
+ return *node_;
+}
+
prefix_ senf::console::LinkNode::ptr senf::console::LinkNode::create(GenericNode & node)
{
GenericNode::ptr p (node.thisptr());
return ptr(new LinkNode(*p));
}
-prefix_ senf::console::GenericNode & senf::console::LinkNode::follow()
- const
-{
- return *node_;
-}
-
prefix_ senf::console::LinkNode::LinkNode(GenericNode & node)
: node_ (node.thisptr())
{}
{}
///////////////////////////////////////////////////////////////////////////
-// senf::console::SyntaxErrorException
-
-prefix_ senf::console::SyntaxErrorException::SyntaxErrorException(std::string const & msg)
- : message_(msg)
-{}
-
-prefix_ senf::console::SyntaxErrorException::~SyntaxErrorException()
- throw()
-{}
-
-prefix_ std::string const & senf::console::SyntaxErrorException::message()
- const
-{
- return message_;
-}
-
-///////////////////////////////////////////////////////////////////////////
// senf::console::CommandNode
prefix_ senf::console::CommandNode::ptr senf::console::CommandNode::thisptr()
///////////////////////////////cci.p///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
+// senf::console::OverloadedCommandNode
+
+prefix_ senf::console::OverloadedCommandNode::ptr senf::console::OverloadedCommandNode::create()
+{
+ return ptr(new OverloadedCommandNode());
+}
+
+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_ unsigned
+senf::console::OverloadedCommandNode::overloadIndex(CommandOverload const & overload)
+{
+ return find(overloads_.begin(), overloads_.end(), CommandOverload::cptr(&overload))
+ - overloads_.begin() + 1;
+}
+
+prefix_ senf::console::OverloadedCommandNode::OverloadedCommandNode()
+{}
+
+///////////////////////////////////////////////////////////////////////////
// senf::console::CommandOverload
prefix_ senf::console::CommandOverload::~CommandOverload()
{}
///////////////////////////////////////////////////////////////////////////
-// senf::console::OverloadedCommandNode
-
-prefix_ senf::console::OverloadedCommandNode::ptr senf::console::OverloadedCommandNode::create()
-{
- return ptr(new OverloadedCommandNode());
-}
-
-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_ unsigned
-senf::console::OverloadedCommandNode::overloadIndex(CommandOverload const & overload)
-{
- return find(overloads_.begin(), overloads_.end(), CommandOverload::cptr(&overload))
- - overloads_.begin() + 1;
-}
-
-prefix_ senf::console::OverloadedCommandNode::OverloadedCommandNode()
-{}
-
-///////////////////////////////////////////////////////////////////////////
// senf::console::SimpleCommandOverload
prefix_ senf::console::SimpleCommandOverload::ptr
).full;
}
+///////////////////////////////////////////////////////////////////////////
+// senf::console::SyntaxErrorException
+
+prefix_ char const * senf::console::SyntaxErrorException::what()
+ const throw()
+{
+ return message().empty() ? "syntax error" : message().c_str();
+}
+
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
//#include "Parse.mpp"
}
///////////////////////////////////////////////////////////////////////////
+// senf::console::SyntaxErrorException
+
+prefix_ senf::console::SyntaxErrorException::SyntaxErrorException(std::string const & msg)
+ : message_(msg)
+{}
+
+prefix_ senf::console::SyntaxErrorException::~SyntaxErrorException()
+ throw()
+{}
+
+prefix_ std::string const & senf::console::SyntaxErrorException::message()
+ const
+{
+ return message_;
+}
+
+///////////////////////////////////////////////////////////////////////////
prefix_ senf::console::CheckedArgumentIteratorWrapper::
CheckedArgumentIteratorWrapper(ParseCommandInfo::ArgumentsRange const & range,
///////////////////////////////cc.p////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::ArgumentInfoBase
+
+prefix_ senf::console::detail::ArgumentInfoBase::~ArgumentInfoBase()
+{}
+
+////////////////////////////////////////////////////////////////////////
// senf::console::ParsedCommandOverloadBase
prefix_ unsigned senf::console::ParsedCommandOverloadBase::v_numArguments()
///////////////////////////////cci.p///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::ArgumentInfoBase
+
+prefix_ senf::console::detail::ArgumentInfoBase::ArgumentInfoBase(std::string const & type_)
+ : type (type_), name (), hasDefault (false)
+{}
+
+///////////////////////////////////////////////////////////////////////////
// senf::console::ParsedCommandOverloadBase
prefix_ senf::console::ParsedCommandOverloadBase::ParsedCommandOverloadBase()
: overload_ (overload), index_ (index)
{}
+prefix_ senf::console::ParsedCommandOverloadBase &
+senf::console::ParsedCommandAttributorBase::overload()
+ const
+{
+ return overload_;
+}
+
prefix_ void senf::console::ParsedCommandAttributorBase::argName(std::string const & name)
const
{
overload().arg(index_).defaultDoc = doc;
}
-prefix_ senf::console::ParsedCommandOverloadBase &
-senf::console::ParsedCommandAttributorBase::overload()
- const
-{
- return overload_;
-}
-
prefix_ void senf::console::ParsedCommandAttributorBase::overloadDoc(std::string const & doc)
const
{
///////////////////////////////cti.p///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-// senf::console::detail::ArgumentInfoBase
-
-prefix_ senf::console::detail::ArgumentInfoBase::ArgumentInfoBase(std::string const & type_)
- : type (type_), name (), hasDefault (false)
-{}
-
-///////////////////////////////////////////////////////////////////////////
// senf::console::detail::ArgumentInfo<ParameterType>
template <class ParameterType>
std::string doc;
ArgumentInfoBase(std::string const & type);
+ virtual ~ArgumentInfoBase();
virtual std::string defaultValueStr() const = 0;
};
// Custom includes
#include <boost/algorithm/string/predicate.hpp>
+#include <boost/format.hpp>
//#include "ProgramOptions.mpp"
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::ProgramOptionsSource::NonOptionContainer
+
+prefix_ senf::console::detail::ProgramOptionsSource::NonOptionContainer::~NonOptionContainer()
+{}
+
+///////////////////////////////////////////////////////////////////////////
// senf::console::detail::ProgramOptionsSource
prefix_ void senf::console::detail::ProgramOptionsSource::v_parse(RestrictedExecutor & executor)
{
- char ** argp (argv_);
- int n (argc_);
+ if (nonOptions_)
+ nonOptions_->clear();
+ if (argc_ <= 1)
+ return;
+ char ** argp (argv_+1);
+ int n (argc_-1);
for (; n; --n, ++argp) {
std::string arg (*argp);
- if (boost::algorithm::starts_with(arg, std::string("--")))
+ if (arg == "--") {
+ for (; n; --n, ++argp)
+ parseNonOption(arg, executor);
+ break;
+ }
+ else if (boost::algorithm::starts_with(arg, std::string("--")) && arg.size() > 2)
parseLongOption(arg.substr(2), executor);
+ else if (boost::algorithm::starts_with(arg, std::string("-")) && arg.size() > 1) {
+ for (std::string::size_type i (1); i<arg.size(); ++i) {
+ char opt (arg[i]);
+ ShortOptions::iterator j (shortOptions_.find(opt));
+ if (j == shortOptions_.end())
+ throw SyntaxErrorException(
+ (boost::format("invalid short option '%c'") % opt).str());
+ std::string param;
+ if (j->second.withArg) {
+ if (i >= arg.size()-1) {
+ if (n > 0) {
+ param = *(++argp);
+ --n;
+ }
+ }
+ else
+ param = arg.substr(i+1);
+ i = arg.size();
+ }
+ std::string longOpt (j->second.longOpt);
+ if (! param.empty() ) {
+ longOpt += "=";
+ longOpt += param;
+ }
+ if (boost::algorithm::starts_with(longOpt, std::string("--")))
+ longOpt = longOpt.substr(2);
+ parseLongOption(longOpt, executor);
+ }
+ }
else
parseNonOption(arg, executor);
}
}
-namespace {
- struct MakeWordToken
- {
- typedef senf::console::Token result_type;
- template <class Range>
- result_type operator()(Range const & r) const
- { return senf::console::WordToken(std::string(boost::begin(r), boost::end(r))); }
- };
-}
-
prefix_ void
senf::console::detail::ProgramOptionsSource::parseLongOption(std::string const & arg,
RestrictedExecutor & executor)
while (b < name.size()) {
std::string::size_type e (name.size());
for (;e != std::string::npos && e > b; e = name.rfind('-', e)) {
- DirectoryNode::ChildrenRange completions (cwd->completions(name.substr(b,e-b)));
- if (completions.size() == 1) {
- path.push_back(WordToken(completions.begin()->first));
- if (e < name.size())
- cwd = cwd->getDirectory(completions.begin()->first).thisptr();
- b = e+1;
- e = b+1;
- break;
+ std::string key (name.substr(b,e-b));
+ if (! cwd->hasChild(key)) {
+ DirectoryNode::ChildrenRange completions (cwd->completions(key));
+ if (completions.size() == 1)
+ key = completions.begin()->first;
+ else
+ continue;
}
+ path.push_back(WordToken(key));
+ if (e < name.size())
+ cwd = cwd->getDirectory(key).thisptr();
+ b = e+1;
+ e = b+1;
+ break;
}
if (e == std::string::npos || e <= b) {
- // This will produce a correct error message later
+ // This will produce a correct error message later or will skip the node,
+ // if parsing is restricted to a subtree
path.push_back(WordToken(name.substr(b)));
b = name.size();
}
prefix_ void
senf::console::detail::ProgramOptionsSource::parseNonOption(std::string const & arg,
RestrictedExecutor & executor)
-{}
+{
+ if (! nonOptions_)
+ throw SyntaxErrorException("invalid non-option argument");
+ nonOptions_->push_back(arg);
+}
///////////////////////////////////////////////////////////////////////////
: argc_ (argc), argv_ (argv)
{}
+prefix_ senf::console::detail::ProgramOptionsSource &
+senf::console::detail::ProgramOptionsSource::alias(char letter, std::string const & longOpt,
+ bool withArg)
+{
+ shortOptions_.insert(std::make_pair(letter, ShortOption(withArg, longOpt)));
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::ProgramOptionsSource::ShortOption
+
+prefix_ senf::console::detail::ProgramOptionsSource::ShortOption::
+ShortOption(bool withArg_, std::string const & longOpt_)
+ : withArg (withArg_), longOpt (longOpt_)
+{}
+
///////////////////////////////////////////////////////////////////////////
// senf::console::ProgramOptions
prefix_ senf::console::ProgramOptions::ProgramOptions(int argc, char ** argv,
DirectoryNode & root)
- : detail::BundleMixin (root)
+ : detail::BundleMixin (root), config_ (add(detail::ProgramOptionsSource::create(argc, argv)))
+{}
+
+prefix_ senf::console::ProgramOptions &
+senf::console::ProgramOptions::alias(char letter, std::string const & longOpt, bool withArg)
{
- add(detail::ProgramOptionsSource::create(argc, argv));
+ config_.alias(letter, longOpt, withArg);
+ return *this;
}
///////////////////////////////////////////////////////////////////////////
--- /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 ProgramOptions inline template implementation */
+
+#include "ProgramOptions.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::ProgramOptionsSource
+
+template <class Container>
+prefix_ senf::console::detail::ProgramOptionsSource &
+senf::console::detail::ProgramOptionsSource::nonOptions(Container & container)
+{
+ nonOptions_.reset(new NonOptionContainerImpl<Container>(container));
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::ProgramOptionsSource::NonOptionContainerImpl
+
+template <class Container>
+prefix_
+senf::console::detail::ProgramOptionsSource::NonOptionContainerImpl<Container>::
+NonOptionContainerImpl(Container & c)
+ : c_ (c)
+{}
+
+template <class Container>
+prefix_ void
+senf::console::detail::ProgramOptionsSource::NonOptionContainerImpl<Container>::clear()
+{
+ c_.clear();
+}
+
+template <class Container>
+prefix_ void
+senf::console::detail::ProgramOptionsSource::NonOptionContainerImpl<Container>::
+push_back(std::string const & value)
+{
+ c_.push_back(value);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ProgramOptions
+
+template <class Container>
+prefix_ senf::console::ProgramOptions &
+senf::console::ProgramOptions::nonOptions(Container & container)
+{
+ config_.nonOptions(container);
+ return *this;
+}
+
+///////////////////////////////cti.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:
///@}
///////////////////////////////////////////////////////////////////////////
+
+ template <class Container>
+ ProgramOptions & nonOptions(Container & container);
+ ProgramOptions & alias(char letter, std::string const & longOpt, bool withArg=false);
+
+ private:
+ detail::ProgramOptionsSource & config_;
};
void parseOptions(int argc, char ** argv, DirectoryNode & root = root());
///////////////////////////////hh.e////////////////////////////////////////
#include "ProgramOptions.cci"
//#include "ProgramOptions.ct"
-//#include "ProgramOptions.cti"
+#include "ProgramOptions.cti"
#endif
\f
#define IH_ProgramOptions_ 1
// Custom includes
+#include <boost/scoped_ptr.hpp>
#include "Parse.hh"
///////////////////////////////ih.p////////////////////////////////////////
class ProgramOptionsSource : public ConfigSource
{
public:
+ typedef boost::intrusive_ptr<ProgramOptionsSource> ptr;
+
static ptr create(int argc, char ** argv);
+
+ template <class Container>
+ ProgramOptionsSource & nonOptions(Container & container);
+ ProgramOptionsSource & alias(char letter, std::string const & longOpt, bool withArg=false);
private:
ProgramOptionsSource(int argc, char ** argv);
void parseLongOption(std::string const & arg, RestrictedExecutor & executor);
void parseNonOption(std::string const & arg, RestrictedExecutor & executor);
+
+ struct NonOptionContainer
+ {
+ virtual ~NonOptionContainer();
+ virtual void clear() = 0;
+ virtual void push_back(std::string const & value) = 0;
+ };
+
+ template <class Container>
+ struct NonOptionContainerImpl
+ : public NonOptionContainer
+ {
+ NonOptionContainerImpl(Container & c);
+
+ void clear();
+ void push_back(std::string const & value);
+
+ Container & c_;
+ };
+
+ struct ShortOption
+ {
+ ShortOption(bool withArg, std::string const & longOpt);
+ bool withArg;
+ std::string longOpt;
+ };
+
+ typedef std::map<char, ShortOption> ShortOptions;
int argc_;
char ** argv_;
CommandParser parser_;
+ ShortOptions shortOptions_;
+ boost::scoped_ptr<NonOptionContainer> nonOptions_;
};
}}}
root.mkdir("name-with-dashes").add("fun-2", &fun2);
{
- char * argv[] = { "--dir1-fun1=foo","--fun2" };
+ char * argv[] = { "", "--dir1-fun1=foo","--fun2" };
senf::console::ProgramOptions opts (sizeof(argv)/sizeof(argv[0]), argv, root);
SENF_CHECK_NO_THROW( opts.parse() );
}
{
- char * argv[] = { "--d-f=foo","--fun" };
+ char * argv[] = { "", "--d-f=foo","--fun" };
senf::console::ProgramOptions opts (sizeof(argv)/sizeof(argv[0]), argv, root);
val1 = "";
}
{
- char * argv[] = { "--name-w-fun" };
+ char * argv[] = { "", "--name-w-fun" };
senf::console::ProgramOptions opts (sizeof(argv)/sizeof(argv[0]), argv, root);
val1 = "";
BOOST_CHECK_EQUAL( val1, "" );
BOOST_CHECK_EQUAL( val2, true );
}
+
+ {
+ char * argv[] = { "", "-ab" };
+ senf::console::ProgramOptions opts(sizeof(argv)/sizeof(argv[0]), argv, root);
+ opts
+ .alias('a', "--dir1-fun1=baz")
+ .alias('b', "--fun2");
+
+ val1 = "";
+ val2 = false;
+
+ SENF_CHECK_NO_THROW( opts.parse() );
+ BOOST_CHECK_EQUAL( val1, "baz" );
+ BOOST_CHECK_EQUAL( val2, true );
+ }
+
+ {
+ char * argv[] = { "", "-badoo" };
+ senf::console::ProgramOptions opts(sizeof(argv)/sizeof(argv[0]), argv, root);
+ opts
+ .alias('a', "--dir1-fun1", true)
+ .alias('b', "--fun2");
+
+ val1 = "";
+ val2 = false;
+
+ SENF_CHECK_NO_THROW( opts.parse() );
+ BOOST_CHECK_EQUAL( val1, "doo" );
+ BOOST_CHECK_EQUAL( val2, true );
+ }
+
+ {
+ char * argv[] = { "", "-a","dii","-b" };
+ senf::console::ProgramOptions opts(sizeof(argv)/sizeof(argv[0]), argv, root);
+ opts
+ .alias('a', "--dir1-fun1", true)
+ .alias('b', "--fun2");
+
+ val1 = "";
+ val2 = false;
+
+ SENF_CHECK_NO_THROW( opts.parse() );
+ BOOST_CHECK_EQUAL( val1, "dii" );
+ BOOST_CHECK_EQUAL( val2, true );
+ }
}
///////////////////////////////cc.e////////////////////////////////////////
}
///////////////////////////////////////////////////////////////////////////
+// senf::console::Client
+
+prefix_ senf::console::Client::~Client()
+{}
+
+prefix_ void senf::console::Client::stop()
+{
+ // THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER removeClient RETURNS
+ server_.removeClient(*this);
+}
+
+prefix_ std::string const & senf::console::Client::name()
+ const
+{
+ return name_;
+}
+
+prefix_ std::string senf::console::Client::promptString()
+ const
+{
+ return name_ + ":" + executor_.cwdPath() + "$ ";
+}
+
+prefix_ senf::console::Client & senf::console::Client::get(std::ostream & os)
+{
+ return dynamic_cast<detail::NonblockingSocketOStream&>(os)->client();
+}
+
+prefix_ senf::console::Client::ClientHandle senf::console::Client::handle()
+ const
+{
+ return handle_;
+}
+
+prefix_ std::ostream & senf::console::Client::stream()
+{
+ return out_t::member;
+}
+
+///////////////////////////////////////////////////////////////////////////
// senf::console::detail::ClientReader
prefix_ senf::console::detail::ClientReader::~ClientReader()
: client_ (client)
{}
-///////////////////////////////////////////////////////////////////////////
-// senf::console::Client
-
-prefix_ senf::console::Client::~Client()
-{}
-
-prefix_ void senf::console::Client::stop()
-{
- // THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER removeClient RETURNS
- server_.removeClient(*this);
-}
-
-prefix_ std::string const & senf::console::Client::name()
- const
-{
- return name_;
-}
-
-prefix_ std::string senf::console::Client::promptString()
- const
-{
- return name_ + ":" + executor_.cwdPath() + "$ ";
-}
-
-prefix_ senf::console::Client & senf::console::Client::get(std::ostream & os)
-{
- return dynamic_cast<detail::NonblockingSocketOStream&>(os)->client();
-}
-
-prefix_ senf::console::Client::ClientHandle senf::console::Client::handle()
- const
-{
- return handle_;
-}
-
-prefix_ std::ostream & senf::console::Client::stream()
-{
- return out_t::member;
-}
-
///////////////////////////////cci.e///////////////////////////////////////
#undef prefix_