Console: Add console logging documentation
[senf.git] / Console / ParsedCommand.mpp
index 3d998c4..2d645d6 100644 (file)
@@ -38,6 +38,8 @@
 #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:
@@ -71,6 +117,7 @@ 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             \
@@ -78,8 +125,16 @@ public:
     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:
@@ -96,16 +151,88 @@ 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) 
 {
@@ -120,8 +247,44 @@ ParsedCommandOverload(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
+{
+    if ( command.arguments().size() > BOOST_PP_ITERATION() )
+        throw SyntaxErrorException("invalid number of arguments");
+    int nDefaults ( BOOST_PP_ITERATION() - command.arguments().size() );
+
+    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
 {
@@ -135,20 +298,21 @@ v_execute(std::ostream & os, ParseCommandInfo const & command)
     riterator const i_end (boost::rend(command.arguments()));
 
 #   define mpp_l(z,n,d)                                                                           \
-        if (i == i_end)                                                                           \
-            throw SyntaxErrorException("invalid number of arguments");                            \
-        mpp_ArgTypeN(n) mpp_ArgN(n) (arg< mpp_ArgTypeN(n) >( n ).defaultValue);                   \
-        if (! arg(n).hasDefault || nDefaults-- <= 0)                                              \
-            ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) );
+        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_
 
-    detail::CheckVoidReturn<typename traits::result_type>::call(
-        boost::bind(function_, boost::ref(os)
-                    mpp_TrailingArgs()),
-        os );
+    function_(os mpp_TrailingArgs());
 }
 
 // ////////////////////////////////////////////////////////////////////////
@@ -160,7 +324,7 @@ v_execute(std::ostream & os, ParseCommandInfo const & command)
 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)