\li \e default_value: Arguments default value</td></tr>
</table>
+
+ See senf::console::ParsedArgumentAttributor 'List of all members'
\section console_memberfn Registering member functions
Member functions are supported like non-member functions. They must however be added through a
- senf::console::ScopedDirectory<> instance to bind them to their instance.
+ senf::console::ScopedDirectory instance to bind them to their instance.
\code
class Test
{
public:
- ScopedDirectory<Test> dir;
+ senf::console::ScopedDirectory<Test> dir;
Test(std::string label) : dir(this), label_ (label) {
dir.add("test4", &Test::test2);
\endcode
Binding via senf::console::ScopedDirectory ensures, that the commands are automatically removed
- from the tree when an object is destroyed.
+ from the tree when the object is destroyed.
*/
\f
{};
#endif
+ /** \brief Syntax error parsing command arguments exception
+
+ All errors while parsing the arguments of a command must be signaled by throwing an instance
+ of SyntaxErrorException. This is important, so command overloading works.
+ */
struct SyntaxErrorException : public senf::Exception
{
explicit SyntaxErrorException(std::string const & msg = "");
class OverloadedCommandNode;
+ /** \brief Documentation for a single argument
+
+ This struct is used by CommandOverload::argumentDoc()
+ */
struct ArgumentDoc {
- std::string name;
- std::string type;
- std::string defaultValue;
- std::string doc;
+ std::string name; ///< Argument name
+ std::string type; ///< Argument type (string representation)
+ std::string defaultValue; ///< Default value (string representation) or empty string
+ std::string doc; ///< Documentation for this argument
};
/** \brief Base class for command overload of OverloadedCommandNode
overload, a SyntaxErrorException must be thrown.
Same as execute() */
- unsigned numArguments() const;
+ unsigned numArguments() const; ///< Number of arguments this overload takes
void argumentDoc(unsigned index, ArgumentDoc & doc) const;
- std::string doc() const;
+ ///< Get information on argument \a index
+ /**< The information is returned in \e doc. \e doc must be
+ empty before this call.
+ \pre \a index < numArguments()
+ \param[in] index Argument index
+ \param[outp doc Argument documentation */
+
+ std::string doc() const; ///< Get overload documentation
OverloadedCommandNode & node() const; ///< Access owning node
/**< \pre The command \e must have been added to an
OverloadedCommandNode. */
- unsigned overloadIndex() const;
+
+ unsigned overloadIndex() const; ///< Get index of overload in it's OverloadedCommandNode
protected:
CommandOverload();
private:
#endif
virtual unsigned v_numArguments() const = 0;
+ ///< Return the number of arguments
+ /**< This member must be implemented in the derived class to
+ return the number of arguments, the command expects. */
+
virtual void v_argumentDoc(unsigned index, ArgumentDoc & doc) const = 0;
+ ///< Return argument documentation
+ /**< The member must be implemented int the derived class to
+ return all documentation information for the \a
+ index'th parameter in \a doc. */
+
virtual std::string v_doc() const = 0;
+ ///< Return overload documentation
+ /**< This member must be implemented in the derived class to
+ return the overloads documentation string. */
+
virtual void v_execute(std::ostream & os, ParseCommandInfo const & command) const = 0;
+ ///< Execute the overload
+ /**< This member must be implemented in the derived class
+ o execute the overload. */
private:
OverloadedCommandNode * node_;
template <class Command>
Command & add(boost::intrusive_ptr<Command> overload); ///< Add an additional overload
- ptr thisptr();
- cptr thisptr() const;
-
OverloadedCommandNode & doc(std::string const & doc);
///< Assign global help for all overloads
unsigned overloadIndex(CommandOverload const & overload);
+ ///< Return the overload index for \a overload
+ /**< overloadIndex returns the index of \a overload in the
+ internal list of overloads. */
- protected:
+ ptr thisptr();
+ cptr thisptr() const;
private:
OverloadedCommandNode();
SimpleCommandOverload & doc(std::string const & doc);
///< Assign overload specific documentation
- protected:
-
private:
- SimpleCommandOverload(Function fn);
+ explicit SimpleCommandOverload(Function fn);
virtual unsigned v_numArguments() const;
virtual void v_argumentDoc(unsigned index, ArgumentDoc & doc) const;
friend class detail::ParserAccess;
};
- /** \brief Console command
+ /** \brief Single parsed console command
Every command parsed is returned in a ParseCommandInfo instance. This information is purely
taken from the parser, no semantic information is attached at this point, the config/console
- is not involved in any why. ParseCommandInfo consist of
+ node tree is not involved in any why. ParseCommandInfo consist of
\li the type of command: built-in or normal command represented by a possibly relative path
into the command tree.
constitutes one path element. If the first element is
empty, the path is an absolute path, otherwise it is
relative. If the last element is an empty string, the
- path ends in a '/' char. */
+ path ends with a '/' char. */
ArgumentsRange arguments() const; ///< Command arguments
- /**< The returned range contains one token range for each
+ /**< The returned range contains one TokensRange for each
argument. */
TokensRange tokens() const; ///< All argument tokens
/**< The returned range contains \e all argument tokens in a
+++ /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 ParseParameter public header */
-
-#ifndef HH_ParseParameter_
-#define HH_ParseParameter_ 1
-
-// Custom includes
-#include <iostream>
-#include <boost/intrusive_ptr.hpp>
-#include "../Utils/intrusive_refcount.hh"
-#include "Parse.hh"
-#include "Node.hh"
-
-//#include "ParseParameter.mpp"
-///////////////////////////////hh.p////////////////////////////////////////
-
-namespace senf {
-namespace console {
-namespace detail {
-
- struct ParameterInfoBase
- : public intrusive_refcount
- {
- typedef boost::intrusive_ptr<ParameterInfoBase> ptr;
-
- std::string type;
- std::string name;
- bool hasDefault;
- std::string doc;
-
- ParameterInfoBase(std::string const & type);
-
- virtual std::string defaultValueStr() const = 0;
- };
-
- template <class ParameterType>
- struct ParameterInfo
- : public ParameterInfoBase
- {
- typedef boost::intrusive_ptr<ParameterInfo> ptr;
-
- static ptr create();
- ParameterInfo();
-
- ParameterType defaultValue;
-
- virtual std::string defaultValueStr() const;
- };
-
- template <class Type>
- struct ReturnValueTraits
- {
- typedef Type type;
-
- template <class Fn>
- static void callAndWrite(Fn const & fn, std::ostream & os);
- };
-
- template <>
- struct ReturnValueTraits<void>
- {
- typedef void type;
-
- template <class Fn>
- static void callAndWrite(Fn const & fn, std::ostream & os);
- };
-
- template <class Type>
- struct ParameterTraits
- {
- typedef Type type;
- static void parse(ParseCommandInfo::TokensRange const & tokens, Type & out);
- static std::string typeDescription();
- static std::string dump(Type const & value);
- };
-
-}}}
-
-///////////////////////////////hh.e////////////////////////////////////////
-//#include "ParseParameter.cci"
-//#include "ParseParameter.ct"
-#include "ParseParameter.cti"
-#endif
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
const
{
BOOST_ASSERT( index < parameters_.size() );
- detail::ParameterInfoBase & arg (*parameters_[index]);
+ detail::ArgumentInfoBase & arg (*parameters_[index]);
doc.name = arg.name.empty()
? (boost::format("arg%d%d") % overloadIndex() % (index+1)).str()
: arg.name;
prefix_ senf::console::ParsedCommandOverloadBase::ParsedCommandOverloadBase()
{}
-prefix_ senf::console::detail::ParameterInfoBase &
+prefix_ senf::console::detail::ArgumentInfoBase &
senf::console::ParsedCommandOverloadBase::arg(unsigned n)
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>
+prefix_ typename senf::console::detail::ArgumentInfo<ParameterType>::ptr
+senf::console::detail::ArgumentInfo<ParameterType>::create()
+{
+ return ptr(new ArgumentInfo());
+}
+
+template <class ParameterType>
+prefix_ senf::console::detail::ArgumentInfo<ParameterType>::ArgumentInfo()
+ : ArgumentInfoBase ( ArgumentTraits<ParameterType>::description() ),
+ defaultValue ()
+{}
+
+template <class ParameterType>
+prefix_ std::string senf::console::detail::ArgumentInfo<ParameterType>::defaultValueStr()
+ const
+{
+ return hasDefault ? ArgumentTraits<ParameterType>::str(defaultValue) : "";
+}
+
+///////////////////////////////////////////////////////////////////////////
// senf::console::ParsedCommandOverloadBase
template <class Type>
-prefix_ senf::console::detail::ParameterInfo<Type> &
+prefix_ senf::console::detail::ArgumentInfo<Type> &
senf::console::ParsedCommandOverloadBase::arg(unsigned n)
const
{
- return dynamic_cast<detail::ParameterInfo<Type> &>(arg(n));
+ return dynamic_cast<detail::ArgumentInfo<Type> &>(arg(n));
}
template <class Type>
prefix_ void senf::console::ParsedCommandOverloadBase::addParameter()
{
- parameters_.push_back(detail::ParameterInfo<Type>::create());
+ parameters_.push_back(detail::ArgumentInfo<Type>::create());
}
///////////////////////////////////////////////////////////////////////////
{}
///////////////////////////////////////////////////////////////////////////
-// senf::console::ParsedAttributeAttributorBase<Overload,Self>
+// senf::console::ParsedArgumentAttributorBase<Overload,Self>
template <class Overload, class Self>
prefix_ Self
-senf::console::ParsedAttributeAttributorBase<Overload,Self>::doc(std::string const & doc)
+senf::console::ParsedArgumentAttributorBase<Overload,Self>::doc(std::string const & doc)
const
{
this->ParsedCommandAttributorBase::nodeDoc(doc);
}
template <class Overload, class Self>
-prefix_ Self senf::console::ParsedAttributeAttributorBase<Overload,Self>::
+prefix_ Self senf::console::ParsedArgumentAttributorBase<Overload,Self>::
overloadDoc(std::string const & doc)
const
{
template <class Overload, class Self>
prefix_
-senf::console::ParsedAttributeAttributorBase<Overload,Self>::
-ParsedAttributeAttributorBase(Overload & overload, unsigned index)
+senf::console::ParsedArgumentAttributorBase<Overload,Self>::
+ParsedArgumentAttributorBase(Overload & overload, unsigned index)
: ParsedCommandAttributor<Overload> (overload, index)
{}
///////////////////////////////////////////////////////////////////////////
-// senf::console::ParsedAttributeAttributor<Overload,index,flag>
+// senf::console::ParsedArgumentAttributor<Overload,index,flag>
template <class Overload, unsigned index, bool flag>
-prefix_ typename senf::console::ParsedAttributeAttributor<Overload,index,flag>::next_type
-senf::console::ParsedAttributeAttributor<Overload,index,flag>::arg()
+prefix_ typename senf::console::ParsedArgumentAttributor<Overload,index,flag>::next_type
+senf::console::ParsedArgumentAttributor<Overload,index,flag>::arg()
const
{
return next();
template <class Overload, unsigned index, bool flag>
template <class ArgumentPack>
-prefix_ typename senf::console::ParsedAttributeAttributor<Overload,index,flag>::next_type
-senf::console::ParsedAttributeAttributor<Overload,index,flag>::
+prefix_ typename senf::console::ParsedArgumentAttributor<Overload,index,flag>::next_type
+senf::console::ParsedArgumentAttributor<Overload,index,flag>::
argInfo(ArgumentPack const & args)
const
{
template <class Overload, unsigned index, bool flag>
template <class Kw, class ArgumentPack>
-prefix_ void senf::console::ParsedAttributeAttributor<Overload,index,flag>::
+prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
argInfo(Kw const &, ArgumentPack const &, boost::mpl::true_)
const
{}
template <class Overload, unsigned index, bool flag>
template <class ArgumentPack>
-prefix_ void senf::console::ParsedAttributeAttributor<Overload,index,flag>::
+prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
argInfo(boost::parameter::keyword<kw::type::name> const &, ArgumentPack const & args,
boost::mpl::false_)
const
template <class Overload, unsigned index, bool flag>
template <class ArgumentPack>
-prefix_ void senf::console::ParsedAttributeAttributor<Overload,index,flag>::
+prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
argInfo(boost::parameter::keyword<kw::type::description> const &, ArgumentPack const & args,
boost::mpl::false_)
const
template <class Overload, unsigned index, bool flag>
template <class ArgumentPack>
-prefix_ void senf::console::ParsedAttributeAttributor<Overload,index,flag>::
+prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
argInfo(boost::parameter::keyword<kw::type::default_value> const &, ArgumentPack const & args,
boost::mpl::false_)
const
template <class Overload, unsigned index, bool flag>
prefix_
-senf::console::ParsedAttributeAttributor<Overload,index,flag>::
-ParsedAttributeAttributor(Overload & overload)
- : ParsedAttributeAttributorBase<Overload, ParsedAttributeAttributor> (overload, index)
+senf::console::ParsedArgumentAttributor<Overload,index,flag>::
+ParsedArgumentAttributor(Overload & overload)
+ : ParsedArgumentAttributorBase<Overload, ParsedArgumentAttributor> (overload, index)
{}
template <class Overload, unsigned index, bool flag>
-prefix_ typename senf::console::ParsedAttributeAttributor<Overload,index,flag>::next_type
-senf::console::ParsedAttributeAttributor<Overload,index,flag>::next()
+prefix_ typename senf::console::ParsedArgumentAttributor<Overload,index,flag>::next_type
+senf::console::ParsedArgumentAttributor<Overload,index,flag>::next()
const
{
- return ParsedAttributeAttributor<Overload, index+1>(this->overload());
+ return ParsedArgumentAttributor<Overload, index+1>(this->overload());
}
template <class Overload, unsigned index, bool flag>
-prefix_ void senf::console::ParsedAttributeAttributor<Overload,index,flag>::
+prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
defaultValue(value_type const & value)
const
{
}
///////////////////////////////////////////////////////////////////////////
-// senf::console::ParsedAttributeAttributor<Overload, index, false>
+// senf::console::ParsedArgumentAttributor<Overload, index, false>
template <class Overload, unsigned index>
prefix_
-senf::console::ParsedAttributeAttributor<Overload, index, false>::
-ParsedAttributeAttributor(Overload & overload)
- : ParsedAttributeAttributorBase< Overload,
- ParsedAttributeAttributor<Overload, index, false> > (overload, index)
+senf::console::ParsedArgumentAttributor<Overload, index, false>::
+ParsedArgumentAttributor(Overload & overload)
+ : ParsedArgumentAttributorBase< Overload,
+ ParsedArgumentAttributor<Overload, index, false> > (overload, index)
{}
///////////////////////////////////////////////////////////////////////////
}
template <class Function>
-prefix_ senf::console::ParsedAttributeAttributor<
+prefix_ senf::console::ParsedArgumentAttributor<
senf::console::ParsedCommandOverload<
typename senf::console::detail::ParsedCommandTraits<Function>::traits> >
senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name,
typedef detail::ParsedCommandTraits<Function> CmdTraits;
typedef ParsedCommandOverload<typename CmdTraits::traits> Overload;
- typedef ParsedAttributeAttributor<Overload> Attributor;
+ typedef ParsedArgumentAttributor<Overload> Attributor;
return Attributor(
cmdNode.add( CreateParsedCommandOverload<
}
template <class Owner, class Function>
-prefix_ senf::console::ParsedAttributeAttributor<
+prefix_ senf::console::ParsedArgumentAttributor<
senf::console::ParsedCommandOverload<
typename senf::console::detail::ParsedCommandTraits<Function>::traits> >
senf::console::
typedef detail::ParsedCommandTraits<Function> CmdTraits;
typedef ParsedCommandOverload<typename CmdTraits::traits> Overload;
- typedef ParsedAttributeAttributor<Overload> Attributor;
+ typedef ParsedArgumentAttributor<Overload> Attributor;
return Attributor(
cmdNode.add( CreateParsedCommandOverload<
senf::membind(fn,&owner)) ) );
}
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::CheckVoidReturn<Type>
+
+template <class Type>
+template <class Fn>
+prefix_ void senf::console::detail::CheckVoidReturn<Type>::call(Fn fn, std::ostream & os)
+{
+ ReturnValueTraits<Type>::format(fn(),os);
+ os << "\n";
+}
+
+template <class Fn>
+prefix_ void senf::console::detail::CheckVoidReturn<void>::call(Fn fn, std::ostream & os)
+{
+ fn();
+}
+
///////////////////////////////cti.e///////////////////////////////////////
#undef prefix_
#include <boost/parameter/parameters.hpp>
#include "../config.hh"
#include "OverloadedCommand.hh"
-#include "ParseParameter.hh"
+#include "Traits.hh"
#include "../Utils/type_traits.hh"
#include "ParsedCommand.ih"
namespace senf {
namespace console {
+ namespace detail { class ArgumentInfoBase; }
+
/** \brief CommandOverload implementation with automatic argument parsing
ParsedCommandOverloadBase implements a CommandOverload implementation supporting automatic
\endcode
There are quite a number of additional parameters available to be set. These parameters are
- documented in ParsedAttributeAttributor. Parameters are set by adding them as additional
+ documented in ParsedArgumentAttributor. Parameters are set by adding them as additional
calls after adding the node:
\code
used as argument type.
However, argument parsing can be configured by specializing
- senf::console::detail::ParameterTraits. See that class for more information.
+ senf::console::ArgumentTraits. See that class for more information.
\section overload_format Custom return-value formatters
By default, return values are streamed to an ostream. This automatically allows any
streamable type to be used as return value. To add new types or customize the formating, the
- senf::console::detail::ReturnValueTraits template needs to be specialized for that type. See
+ senf::console::ReturnValueTraits template needs to be specialized for that type. See
that class for more information.
\ingroup console_commands
public:
typedef boost::intrusive_ptr<ParsedCommandOverloadBase> ptr;
- detail::ParameterInfoBase & arg(unsigned n) const;
- template <class Type> detail::ParameterInfo<Type> & arg(unsigned n) const;
+ detail::ArgumentInfoBase & arg(unsigned n) const;
+ template <class Type> detail::ArgumentInfo<Type> & arg(unsigned n) const;
void doc(std::string const & d);
virtual void v_argumentDoc(unsigned index, ArgumentDoc & doc) const;
virtual std::string v_doc() const;
- typedef std::vector<detail::ParameterInfoBase::ptr> Parameters;
+ typedef std::vector<detail::ArgumentInfoBase::ptr> Parameters;
Parameters parameters_;
std::string doc_;
};
+ /** \brief Parsed command overload
+
+ ParsedCommandOverload provides the command overload added to an OverloadedCommandNode for an
+ automatically parsed command.
+
+ This class is normally instantiated automatically when adding a function or member-function
+ pointer as callback to the tree. Manually instantiation this type of overload is \e not
+ simple, since the function signature has to be manipulated correctly to support the optional
+ \c std::ostream first argument.
+
+ \implementation This class is specialized for each supported number of command arguments.
+ */
template <class FunctionTraits, unsigned arity=FunctionTraits::arity>
- class ParsedCommandOverload {};
+ class ParsedCommandOverload : public ParsedCommandOverloadBase
+ {
+ public:
+ typedef boost::intrusive_ptr<ParsedCommandOverload> ptr;
+
+#ifdef DOXYGEN
+ static ptr create(Function fn);
+#endif
+ };
+
+#ifndef DOXYGEN
# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, SENF_CONSOLE_MAX_COMMAND_ARITY, \
SENF_ABSOLUTE_INCLUDE_PATH(Console/ParsedCommand.mpp), \
1))
# include BOOST_PP_ITERATE()
+#endif
+
+ /** \brief Generic ParsedCommandOverladBase attributes
+
+ Attributes for parsed commands are not set directly on the node. They are set via a special
+ attributor temporary returned when adding a parsed command to the tree.
+
+ This class is the base class for those attributors. It provides members which do not depend
+ in any way on the exact type of command added.
+ */
class ParsedCommandAttributorBase
{
public:
- OverloadedCommandNode & node() const;
- operator OverloadedCommandNode & () const;
+ OverloadedCommandNode & node() const; ///< Return the node object
+ operator OverloadedCommandNode & () const; ///< Automatically convert to node object
protected:
ParsedCommandAttributorBase(ParsedCommandOverloadBase & overload, unsigned index);
unsigned index_;
};
+ /** \brief Non argument dependent ParsedCommandBase attributes
+
+ Attributes for parsed commands are not set directly on the node. They are set via a special
+ attributor temporary returned when adding a parsed command to the tree.
+
+ This class adds all those members, which do depend on the type of command added (and thereby
+ on that commands signature) but do not depend on the type of any single argument.
+
+ \fixme Implement compile-time checking, that after a defaulted arg only defaulted args are
+ allowed.
+ */
template <class Overload>
class ParsedCommandAttributor
: public ParsedCommandAttributorBase
{
public:
- Overload & overload() const;
+ Overload & overload() const; ///< Get the command overload
protected:
ParsedCommandAttributor(Overload & overload, unsigned index);
private:
};
-
+
+ /** \brief Keyword argument tags
+
+ The tags defined in this namespace are used as keyword arguments via the <a
+ href="http://www.boost.org/doc/libs/1_33_1/libs/parameter/doc/html/index.html">Boost.Parameter</a>
+ library.
+
+ For the keyword tags, the standard C++ scoping rules apply:
+ \li Either qualify them with their complete namespace: <tt>arg( senf::console::kw::name =
+ "name" )</tt>
+ \li or use a namespace alias: <tt>namespace kw = senf::console::kw; arg( kw::name = "name"
+ );</tt>
+ \li import the keywords into your namespace: <tt>using namespace senf::console::kw; arg(
+ name = "name");</tt>
+
+ The second alternative is preferred, the <tt>using namespace</tt> directive may be used as
+ long as the keyword names do not clash with another visible symbol.
+ */
namespace kw {
- BOOST_PARAMETER_KEYWORD(type, name);
- BOOST_PARAMETER_KEYWORD(type, description);
- BOOST_PARAMETER_KEYWORD(type, default_value);
+ BOOST_PARAMETER_KEYWORD(type, name) ///< Argument name
+ BOOST_PARAMETER_KEYWORD(type, description) ///< One-line Argument description
+ BOOST_PARAMETER_KEYWORD(type, default_value) ///< Argument default value
}
+ /** \brief Derived class dependent ParsedCommandBase attributes
+
+ Attributes for parsed commands are not set directly on the node. They are set via a special
+ attributor temporary returned when adding a parsed command to the tree.
+
+ This class adds all those members, which do not depend on any specific argument but which
+ need to return the correct attributor type.
+ */
template <class Overload, class Self>
- class ParsedAttributeAttributorBase
+ class ParsedArgumentAttributorBase
: public ParsedCommandAttributor<Overload>
{
public:
- Self doc(std::string const & doc) const;
- Self overloadDoc(std::string const & doc) const;
+ Self doc(std::string const & doc) const; ///< Set documentation for all overloads
+ Self overloadDoc(std::string const & doc) const; ///< Set overload specific documentation
protected:
- ParsedAttributeAttributorBase(Overload & overload, unsigned index);
+ ParsedArgumentAttributorBase(Overload & overload, unsigned index);
private:
};
+
+ /** \brief Argument dependent ParsedCommandBase attributes
+
+ Attributes for parsed commands are not set directly on the node. They are set via a special
+ attributor temporary returned when adding a parsed command to the tree.
+
+ This class adds all those members, which depend on a specific argument. Each call to \c arg
+ will advance to the next argument.
+ */
template < class Overload,
unsigned index=0,
bool flag=(index < unsigned(Overload::traits::arity)) >
- class ParsedAttributeAttributor
- : public ParsedAttributeAttributorBase< Overload,
- ParsedAttributeAttributor<Overload, index, flag> >
+ class ParsedArgumentAttributor
+ : public ParsedArgumentAttributorBase< Overload,
+ ParsedArgumentAttributor<Overload, index, flag> >
{
+ typedef boost::parameter::parameters<
+ kw::type::name,
+ kw::type::description,
+ kw::type::default_value> arg_params;
+
public:
+ typedef OverloadedCommandNode node_type;
+ typedef ParsedArgumentAttributor return_type;
+
typedef typename senf::function_traits_arg_type<
typename Overload::traits, int(index) >::type arg_type;
typedef typename senf::remove_cvref< arg_type >::type value_type;
- typedef ParsedAttributeAttributor<Overload, index+1> next_type;
+ typedef ParsedArgumentAttributor<Overload, index+1> next_type;
- typedef OverloadedCommandNode node_type;
- typedef ParsedAttributeAttributor return_type;
+ next_type arg() const; ///< Set argument attributes
+ /**< This member changes the attributes for the current
+ argument. The attributes are passed to arg() as keyword
+ arguments using the <a
+ href="http://www.boost.org/doc/libs/1_33_1/libs/parameter/doc/html/index.html">Boost.Parameter</a>
+ library. The valid keywords are defined in the
+ senf::console::kw namespace.
- typedef boost::parameter::parameters<
- kw::type::name,
- kw::type::description,
- kw::type::default_value> arg_params;
+ This member is only present, if there is an argument at
+ the current index. */
- next_type arg() const;
+#ifndef DOXYVEN
# define BOOST_PP_ITERATION_PARAMS_1 \
(4, (1, 3, SENF_ABSOLUTE_INCLUDE_PATH(Console/ParsedCommand.mpp), 5))
# include BOOST_PP_ITERATE()
+#endif
+
private:
- explicit ParsedAttributeAttributor(Overload & overload);
+ explicit ParsedArgumentAttributor(Overload & overload);
template <class ArgumentPack>
next_type argInfo(ArgumentPack const & args) const;
-
template <class Kw, class ArgumentPack>
void argInfo(Kw const &, ArgumentPack const &, boost::mpl::true_)
const;
+
template <class ArgumentPack>
void argInfo(boost::parameter::keyword<kw::type::name> const &,
ArgumentPack const & args, boost::mpl::false_)
void defaultValue(value_type const & value) const;
template <class O, unsigned i, bool f>
- friend class ParsedAttributeAttributor;
+ friend class ParsedArgumentAttributor;
+
+#ifndef DOXYGEN
template <class Function>
- friend ParsedAttributeAttributor<
+ friend ParsedArgumentAttributor<
ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int);
template <class Owner, class Function>
- friend ParsedAttributeAttributor<
+ friend ParsedArgumentAttributor<
ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
Function fn, int,
typename boost::enable_if_c<
detail::ParsedCommandTraits<Function>::is_member>::type * = 0);
+
+#endif
};
+#ifndef DOXYGEN
+
template <class Overload, unsigned index>
- class ParsedAttributeAttributor<Overload, index, false>
- : public ParsedAttributeAttributorBase< Overload,
- ParsedAttributeAttributor<Overload, index, false> >
+ class ParsedArgumentAttributor<Overload, index, false>
+ : public ParsedArgumentAttributorBase< Overload,
+ ParsedArgumentAttributor<Overload, index, false> >
{
public:
typedef OverloadedCommandNode node_type;
- typedef ParsedAttributeAttributor return_type;
+ typedef ParsedArgumentAttributor return_type;
private:
- explicit ParsedAttributeAttributor(Overload & overload);
+ explicit ParsedArgumentAttributor(Overload & overload);
template <class O, unsigned i, bool f>
- friend class ParsedAttributeAttributor;
+ friend class ParsedArgumentAttributor;
template <class Function>
- friend ParsedAttributeAttributor<
+ friend ParsedArgumentAttributor<
ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int);
template <class Owner, class Function>
- friend ParsedAttributeAttributor<
+ friend ParsedArgumentAttributor<
ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
Function fn, int,
detail::ParsedCommandTraits<Function>::is_member>::type * = 0);
};
-#ifndef DOXYGEN
-
template <class Function>
- ParsedAttributeAttributor<
+ ParsedArgumentAttributor<
ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int);
template <class Owner, class Function>
- ParsedAttributeAttributor<
+ ParsedArgumentAttributor<
ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
Function fn, int,
#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
BOOST_TYPEOF_REGISTER_TEMPLATE(senf::console::ParsedCommandOverload, (class,unsigned))
-BOOST_TYPEOF_REGISTER_TEMPLATE(senf::console::ParsedAttributeAttributor, (class, unsigned, bool))
+BOOST_TYPEOF_REGISTER_TEMPLATE(senf::console::ParsedArgumentAttributor, (class, unsigned, bool))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function_traits, 1)
///////////////////////////////hh.e////////////////////////////////////////
namespace console {
namespace detail {
+#ifndef DOXYGEN
+
+ struct ArgumentInfoBase
+ : public intrusive_refcount
+ {
+ typedef boost::intrusive_ptr<ArgumentInfoBase> ptr;
+
+ std::string type;
+ std::string name;
+ bool hasDefault;
+ std::string doc;
+
+ ArgumentInfoBase(std::string const & type);
+
+ virtual std::string defaultValueStr() const = 0;
+ };
+
+ template <class ParameterType>
+ struct ArgumentInfo
+ : public ArgumentInfoBase
+ {
+ typedef boost::intrusive_ptr<ArgumentInfo> ptr;
+
+ static ptr create();
+ ArgumentInfo();
+
+ ParameterType defaultValue;
+
+ virtual std::string defaultValueStr() const;
+ };
+
template <class Function, bool isFN=senf::is_any_function<Function>::value>
struct ParsedCommandTraits
{};
+ // FirstArgType returns void, if the function has no arguments, otherwise it returns arg1_type
+
template <class Traits, bool flag=(Traits::arity>0)>
struct FirstArgType
{
struct ParsedCommandTraits<Function, true>
{
typedef Function base_type;
- typedef typename senf::remove_member_pointer<
- typename boost::remove_pointer<base_type>::type>::type function_type;
+ typedef typename senf::remove_any_pointer<base_type>::type function_type;
typedef boost::function_traits<function_type> base_traits;
-
typedef typename FirstArgType<base_traits>::type first_arg_type;
static const bool has_ostream_arg = boost::is_same<first_arg_type, std::ostream &>::value;
typedef typename senf::member_class<base_type>::type class_type;
};
+ template <class Type>
+ struct CheckVoidReturn
+ {
+ template <class Fn>
+ static void call(Fn fn, std::ostream & os);
+ };
+
+ template <>
+ struct CheckVoidReturn<void>
+ {
+ template <class Fn>
+ static void call(Fn fn, std::ostream & os);
+ };
+
+#endif
+
}}}
///////////////////////////////ih.e////////////////////////////////////////
# define mpp_l(z,n,d) \
mpp_ArgTypeN(n) mpp_ArgN(n) (arg< mpp_ArgTypeN(n) >( n ).defaultValue); \
if (i != i_end) \
- detail::ParameterTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) );
+ ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) );
BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
# undef mpp_l
- // Now call the function binding the arguments to the values parsed above. callAndWrite is
- // specialized to ignore a 'void' return value but automatically write all other values to the
- // output stream.
- detail::ReturnValueTraits<typename traits::result_type>::callAndWrite(
+ detail::CheckVoidReturn<typename traits::result_type>::call(
boost::bind(function_, boost::ref(os)
mpp_TrailingArgs()),
os );
Owner * owner_;
};
+#ifndef DOXYGEN
+
template <>
class ScopedDirectory<void> : public ScopedDirectoryBase
{
Object const & ob);
};
-#ifndef DOXYGEN
template <class Owner, class Function>
SimpleCommandNode & senf_console_add_node(
DirectoryNode & node, Owner & owner, std::string const & name, Function const & fn, ...);
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file
- \brief ParseParameter inline template implementation */
+ \brief Traits inline template implementation */
-//#include "ParseParameter.ih"
+//#include "Traits.ih"
// Custom includes
#include "../Utils/TypeInfo.hh"
///////////////////////////////cti.p///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-// senf::console::detail::ParameterInfoBase
-
-prefix_ senf::console::detail::ParameterInfoBase::ParameterInfoBase(std::string const & type_)
- : type (type_), name (), hasDefault (false)
-{}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::console::detail::ParameterInfo<ParameterType>
-
-template <class ParameterType>
-prefix_ typename senf::console::detail::ParameterInfo<ParameterType>::ptr
-senf::console::detail::ParameterInfo<ParameterType>::create()
-{
- return ptr(new ParameterInfo());
-}
-
-template <class ParameterType>
-prefix_ senf::console::detail::ParameterInfo<ParameterType>::ParameterInfo()
- : ParameterInfoBase ( ParameterTraits<ParameterType>::typeDescription() ),
- defaultValue ()
-{}
-
-template <class ParameterType>
-prefix_ std::string senf::console::detail::ParameterInfo<ParameterType>::defaultValueStr()
- const
-{
- return hasDefault ? ParameterTraits<ParameterType>::dump(defaultValue) : "";
-}
-
-///////////////////////////////////////////////////////////////////////////
// senf::console::detail::ReturnValueTraits<Type>
template <class Type>
-template <class Fn>
-prefix_ void senf::console::detail::ReturnValueTraits<Type>::callAndWrite(Fn const & fn,
- std::ostream & os)
+prefix_ void senf::console::ReturnValueTraits<Type>::format(Type const & value,
+ std::ostream & os)
{
- os << fn() << "\n";
-}
-
-template <class Fn>
-prefix_ void senf::console::detail::ReturnValueTraits<void>::callAndWrite(Fn const & fn,
- std::ostream & os)
-{
- fn();
+ os << value;
}
///////////////////////////////////////////////////////////////////////////
-// senf::console::detail::ParameterTraits<Type>
+// senf::console::ArgumentTraits<Type>
template <class Type>
-prefix_ void senf::console::detail::ParameterTraits<Type>::
+prefix_ void senf::console::ArgumentTraits<Type>::
parse(ParseCommandInfo::TokensRange const & tokens, Type & out)
{
if (tokens.size() != 1)
throw SyntaxErrorException("parameter syntax error");
+
try {
out = boost::lexical_cast<Type>(tokens.begin()[0].value());
}
}
template <class Type>
-prefix_ std::string senf::console::detail::ParameterTraits<Type>::typeDescription()
+prefix_ std::string senf::console::ArgumentTraits<Type>::description()
{
std::string type (prettyName(typeid(Type)));
std::string::size_type i (type.rfind(':'));
}
template <class Type>
-prefix_ std::string senf::console::detail::ParameterTraits<Type>::dump(Type const & value)
+prefix_ std::string senf::console::ArgumentTraits<Type>::str(Type const & value)
{
return boost::lexical_cast<std::string>(value);
}
--- /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 Traits public header */
+
+#ifndef HH_Traits_
+#define HH_Traits_ 1
+
+// Custom includes
+#include <iostream>
+#include <boost/intrusive_ptr.hpp>
+#include "../Utils/intrusive_refcount.hh"
+#include "Parse.hh"
+#include "Node.hh"
+
+//#include "Traits.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace console {
+
+ /** \brief Customize return value formating
+
+ ReturnValueTraits provides return value formatting. The default implementation provided here
+ will just write the value to the output stream.
+
+ To customize this behavior for some type, specialize this class for the type.
+
+ The output should \e not end in a newline since one is added automatically.
+ */
+ template <class Type>
+ struct ReturnValueTraits
+ {
+ typedef Type type;
+
+ static void format(Type const & value, std::ostream & os);
+ ///< Write \a value to \a os
+ };
+
+ /** \brief Customize argument parsing
+
+ ArgumentTraits provides argument parsing, Additionally, this class provides a way to get a
+ string-description of a type and to convert a value back into it's string representation
+ used to display default values.
+
+ The default implementation provided here will use \c boost::lexical_cast and thereby \c
+ iostreams to convert an argument consisting of a single input token into the required
+ type. Types are named by returning the last component of the fully scoped name (e.g. \c
+ "string" for \c std::string). Values are formatted again using \c boost::lexical_cast.
+
+ To customize this behavior for some type, specialize this class for the type.
+ */
+ template <class Type>
+ struct ArgumentTraits
+ {
+ typedef Type type;
+
+ static void parse(ParseCommandInfo::TokensRange const & tokens, Type & out);
+ ///< Parse token range into value
+ /**< This function needs to parse \a tokens and write the
+ parsed value into \a out. This function needs to parse
+ the \e complete list of tokens, additional tokens must
+ be considered as syntax error.
+ \throws SyntaxErrorException
+ \param[in] tokens tokens to parse
+ \param[out] out parsed value */
+
+ static std::string description(); ///< String description of type
+ /**< Returns the string description of \a Type. Used to
+ generate online help. */
+ static std::string str(Type const & value); ///< Stringify value
+ /**< To show default values in the online help, this
+ function converts a value back into a one-line string
+ representation. */
+ };
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+//#include "Traits.cci"
+//#include "Traits.ct"
+#include "Traits.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file
- \brief ParseParameter.test unit tests */
+ \brief Traits.test unit tests */
-//#include "ParseParameter.test.hh"
-//#include "ParseParameter.test.ih"
+//#include "Traits.test.hh"
+//#include "Traits.test.ih"
// Custom includes
-#include "ParseParameter.hh"
+#include "Traits.hh"
#include "../Utils/auto_unit_test.hh"
#include <boost/test/test_tools.hpp>
return ConcretePacket(interpreter::create(size,senf::noinit));
}
+#ifndef DOXYGEN
+
template <class PacketType>
template <class ForwardReadableRange>
prefix_ senf::ConcretePacket<PacketType> senf::ConcretePacket<PacketType>::
return ConcretePacket(interpreter::createAfter(packet.ptr()));
}
+#endif
+
template <class PacketType>
prefix_ senf::ConcretePacket<PacketType>
senf::ConcretePacket<PacketType>::createAfter(Packet packet, senf::NoInit_t)
"SENF_LOG_CLASS_AREA()=" \
"SENF_LOG_DEFAULT_AREA(area)=" \
"SENF_LOG_DEFAULT_STREAM(stream)=" \
- "BOOST_PP_ITERATE()="
+ "BOOST_PP_ITERATE()=" \
+ "BOOST_PARAMETER_KEYWORD(ns, name)=unspecified_keyword_type name;"
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
<?xml version="1.0" encoding="utf-8"?>\r
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"\r
+<xsl:stylesheet version="1.0"\r
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"\r
xmlns:str="http://exslt.org/strings">\r
\r
<xsl:output \r