#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/arithmetic/sub.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/bind.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/at.hpp>
// ///////////////////////////mpp.p////////////////////////////////////////
#elif BOOST_PP_IS_ITERATING // ////////////////////////////////////////////
#define mpp_ArgTypeN(n) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(n)), _type)
#define mpp_ArgN(n) BOOST_PP_CAT(arg, BOOST_PP_INC(n))
-#define mpp_ArgTypes_(z,n,d) typename traits::mpp_ArgTypeN(n)
-#define mpp_TrailingArgTypes() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_ArgTypes_, _ )
+#define mpp_TrailingArgTypes_(z,n,d) typename traits::mpp_ArgTypeN(n)
+#define mpp_TrailingArgTypes() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_TrailingArgTypes_, _ )
-#define mpp_Args_(z,n,d) boost::cref(mpp_ArgN(n))
+#define mpp_ArgTypes_(z,n,d) mpp_ArgTypeN(n)
+#define mpp_ArgTypes() BOOST_PP_ENUM( BOOST_PP_ITERATION(), mpp_ArgTypes_, _ )
+
+#define mpp_Args_(z,n,d) mpp_ArgN(n)
#define mpp_TrailingArgs() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_Args_, _ )
#define mpp_BindArgs_(z,n,d) BOOST_PP_CAT( _, BOOST_PP_INC(BOOST_PP_INC(n)))
// Header file (.hh)
+template <class FunctionTraits, class ReturnValue>
+class ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >
+ : public ParsedCommandOverloadBase
+{
+public:
+ typedef boost::intrusive_ptr<ParsedCommandOverload> ptr;
+ typedef FunctionTraits traits;
+ typedef boost::function<typename traits::result_type(std::ostream &
+ mpp_TrailingArgTypes())> Function;
+ typedef typename senf::remove_cvref<typename traits::result_type>::type result_type;
+ typedef boost::function<void (result_type const &, std::ostream &)> Formatter;
+
+# define mpp_l(z,n,d) \
+ typedef typename senf::remove_cvref< typename traits::mpp_ArgTypeN(n) >::type \
+ mpp_ArgTypeN(n);
+ BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
+# undef mpp_l
+
+ typedef boost::mpl::vector< mpp_ArgTypes() > arg_types;
+
+ static ptr create(Function fn);
+
+ void formatter(Formatter f);
+
+ using ParsedCommandOverloadBase::arg;
+ template <unsigned n>
+ detail::ArgumentInfo<typename boost::mpl::at_c<arg_types, n>::type> & arg() const;
+
+ void function(Function fn);
+
+protected:
+
+private:
+ ParsedCommandOverload(Function fn);
+
+ virtual void v_execute(std::ostream & os, ParseCommandInfo const & command) const;
+
+ Function function_;
+ Formatter formatter_;
+};
+
template <class FunctionTraits>
-class ParsedCommandOverload<FunctionTraits, BOOST_PP_ITERATION() >
+class ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >
: public ParsedCommandOverloadBase
{
public:
typedef FunctionTraits traits;
typedef boost::function<typename traits::result_type(std::ostream &
mpp_TrailingArgTypes())> Function;
+ typedef void result_type;
# define mpp_l(z,n,d) \
typedef typename senf::remove_cvref< typename traits::mpp_ArgTypeN(n) >::type \
BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
# undef mpp_l
+ typedef boost::mpl::vector< mpp_ArgTypes() > arg_types;
+
static ptr create(Function fn);
+ using ParsedCommandOverloadBase::arg;
+ template <unsigned n>
+ detail::ArgumentInfo<typename boost::mpl::at_c<arg_types, n>::type> & arg() const;
+
+ void function(Function fn);
+
protected:
private:
// inline template implementation (.cti)
+template <class FunctionTraits, class ReturnValue>
+prefix_ typename senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::ptr
+senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
+create(Function fn)
+{
+ return ptr(new ParsedCommandOverload(fn));
+}
+
+template <class FunctionTraits, class ReturnValue>
+void
+senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
+formatter(Formatter f)
+{
+ formatter_ = f;
+}
+
+template <class FunctionTraits, class ReturnValue>
+template <unsigned n>
+senf::console::detail::ArgumentInfo<
+ typename boost::mpl::at_c<
+ typename senf::console::ParsedCommandOverload<
+ FunctionTraits, ReturnValue, BOOST_PP_ITERATION()>::arg_types,
+ n>::type> &
+senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
+arg() const
+{
+ return static_cast< detail::ArgumentInfo<
+ typename boost::mpl::at_c<arg_types, n>::type > & >(arg(n));
+}
+
+template <class FunctionTraits, class ReturnValue>
+void
+senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
+function(Function fn)
+{
+ function_ = fn;
+}
+
+template <class FunctionTraits, class ReturnValue>
+prefix_
+senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION()>::
+ParsedCommandOverload(Function fn)
+ : function_ (fn)
+{
+# define mpp_l(z,n,d) addParameter< mpp_ArgTypeN(n) >();
+ BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
+# undef mpp_l
+}
+
template <class FunctionTraits>
-prefix_ typename senf::console::ParsedCommandOverload<FunctionTraits, BOOST_PP_ITERATION() >::ptr
-senf::console::ParsedCommandOverload<FunctionTraits, BOOST_PP_ITERATION() >::create(Function fn)
+prefix_ typename senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::ptr
+senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
+create(Function fn)
{
return ptr(new ParsedCommandOverload(fn));
}
template <class FunctionTraits>
+template <unsigned n>
+senf::console::detail::ArgumentInfo<
+ typename boost::mpl::at_c<
+ typename senf::console::ParsedCommandOverload<
+ FunctionTraits, void, BOOST_PP_ITERATION()>::arg_types,
+ n>::type> &
+senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
+arg() const
+{
+ return static_cast< detail::ArgumentInfo<
+ typename boost::mpl::at_c<arg_types, n>::type > & >(arg(n));
+}
+
+template <class FunctionTraits>
+void
+senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
+function(Function fn)
+{
+ function_ = fn;
+}
+
+template <class FunctionTraits>
prefix_
-senf::console::ParsedCommandOverload<FunctionTraits,BOOST_PP_ITERATION()>::
+senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
ParsedCommandOverload(Function fn)
: function_ (fn)
{
// non-inline template implementation (.ct)
+template <class FunctionTraits, class ReturnValue>
+prefix_ void senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
+v_execute(std::ostream & os, ParseCommandInfo const & command)
+ const
+{
+ // We NEED to know the number of arguments beforehand so we can assign default values
+ // correctly ... hrmpf ...
+ unsigned nArgs ( command.arguments().size() );
+ if ( nArgs > BOOST_PP_ITERATION() )
+ throw SyntaxErrorException("invalid number of arguments");
+ int nDefaults ( BOOST_PP_ITERATION() - nArgs );
+
+ typedef typename boost::range_const_reverse_iterator<ParseCommandInfo::ArgumentsRange>::type
+ riterator;
+ riterator i (boost::rbegin(command.arguments()));
+ riterator const i_end (boost::rend(command.arguments()));
+
+# define mpp_l(z,n,d) \
+ mpp_ArgTypeN(n) mpp_ArgN(n) (arg<n>().defaultValue); \
+ if (! arg(n).hasDefault || nDefaults-- <= 0) { \
+ if (i == i_end) \
+ throw SyntaxErrorException("invalid number of arguments"); \
+ if (arg<n>().parser) \
+ arg<n>().parser( *(i++), mpp_ArgN(n) ); \
+ else \
+ ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) ); \
+ }
+# define mpp_l_(z,n,d) mpp_l(z, BOOST_PP_SUB(BOOST_PP_DEC(BOOST_PP_ITERATION()), n), d)
+ BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l_, _ )
+# undef mpp_l
+# undef mpp_l_
+
+ if (formatter_)
+ formatter_( function_(os mpp_TrailingArgs()), os );
+ else
+ ReturnValueTraits<result_type>::format( function_(os mpp_TrailingArgs()), os );
+ os << "\n";
+}
+
template <class FunctionTraits>
-prefix_ void senf::console::ParsedCommandOverload<FunctionTraits, BOOST_PP_ITERATION() >::
+prefix_ void senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
v_execute(std::ostream & os, ParseCommandInfo const & command)
const
{
- if ( command.arguments().size() > BOOST_PP_ITERATION()
- || (command.arguments().size() < BOOST_PP_ITERATION()
- && ! arg( command.arguments().size() ).hasDefault) )
+ // We NEED to know the number of arguments beforehand so we can assign default values
+ // correctly ... hrmpf ...
+ unsigned nArgs ( command.arguments().size() );
+ if ( nArgs > BOOST_PP_ITERATION() )
throw SyntaxErrorException("invalid number of arguments");
+ int nDefaults ( BOOST_PP_ITERATION() - nArgs );
- ParseCommandInfo::argument_iterator i (command.arguments().begin());
- ParseCommandInfo::argument_iterator const i_end (command.arguments().end());
+ typedef typename boost::range_const_reverse_iterator<ParseCommandInfo::ArgumentsRange>::type
+ riterator;
+ riterator i (boost::rbegin(command.arguments()));
+ riterator const i_end (boost::rend(command.arguments()));
# 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) );
- BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
+ mpp_ArgTypeN(n) mpp_ArgN(n) (arg<n>().defaultValue); \
+ if (! arg(n).hasDefault || nDefaults-- <= 0) { \
+ if (i == i_end) \
+ throw SyntaxErrorException("invalid number of arguments"); \
+ if (arg<n>().parser) \
+ arg<n>().parser( *(i++), mpp_ArgN(n) ); \
+ else \
+ ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) ); \
+ }
+# define mpp_l_(z,n,d) mpp_l(z, BOOST_PP_SUB(BOOST_PP_DEC(BOOST_PP_ITERATION()), n), d)
+ BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l_, _ )
# undef 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(
- boost::bind(function_, boost::ref(os)
- mpp_TrailingArgs()),
- os );
+ function_(os mpp_TrailingArgs());
}
// ////////////////////////////////////////////////////////////////////////
template <class Traits>
struct CreateParsedCommandOverload<Traits, true, BOOST_PP_ITERATION()>
{
- typedef Traits traits;
+ typedef typename Traits::traits traits;
template <class Function>
static typename senf::console::ParsedCommandOverload<traits>::ptr create(Function fn)