From d5acef30819a12b787adfd573909ae079fd20797 Mon Sep 17 00:00:00 2001
From: g0dil <g0dil@wiback.org>
Date: Tue, 8 Apr 2008 09:38:55 +0000
Subject: [PATCH] Console: Add member function argument parsing

---
 Console/ParsedCommand.cti     | 21 ++++++++++++++++
 Console/ParsedCommand.hh      | 11 ++++++++
 Console/ParsedCommand.mpp     |  8 +++---
 Console/ParsedCommand.test.cc | 47 +++++++++++++++++++++++++++++++++++
 Console/ScopedDirectory.cti   |  6 ++---
 Console/ScopedDirectory.hh    |  7 +++---
 6 files changed, 91 insertions(+), 9 deletions(-)

diff --git a/Console/ParsedCommand.cti b/Console/ParsedCommand.cti
index 86a78fc4f..9cdb2792b 100644
--- a/Console/ParsedCommand.cti
+++ b/Console/ParsedCommand.cti
@@ -26,6 +26,7 @@
 #include "ParsedCommand.ih"
 
 // Custom includes
+#include "../Utils/membind.hh"
 
 #define prefix_ inline
 ///////////////////////////////cti.p///////////////////////////////////////
@@ -112,6 +113,26 @@ senf::console::senf_console_add_node(DirectoryNode & node, std::string const & n
                             typename CmdTraits::traits, ! CmdTraits::has_ostream_arg>::create(fn) );
 }
 
+template <class Owner, class Function>
+prefix_ senf::console::ParsedCommandOverload<
+    typename senf::console::detail::ParsedCommandTraits<Function>::traits> &
+senf::console::
+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 *)
+{
+    OverloadedCommandNode & cmdNode (
+        node.hasChild(name) 
+        ? dynamic_cast<OverloadedCommandNode &>(node(name))
+        : node.add(name, OverloadedCommandNode::create()) );
+
+    typedef senf::console::detail::ParsedCommandTraits<Function> CmdTraits;
+
+    return cmdNode.add( CreateParsedCommandOverload<
+                            typename CmdTraits::traits, ! CmdTraits::has_ostream_arg>::create(
+                                senf::membind(fn,&owner)) );
+}
+
 ///////////////////////////////cti.e///////////////////////////////////////
 #undef prefix_
 
diff --git a/Console/ParsedCommand.hh b/Console/ParsedCommand.hh
index cd126c30a..b2fca4867 100644
--- a/Console/ParsedCommand.hh
+++ b/Console/ParsedCommand.hh
@@ -32,6 +32,7 @@
 #include <boost/type_traits/is_member_pointer.hpp>
 #include <boost/type_traits/is_same.hpp>
 #include <boost/mpl/if.hpp>
+#include <boost/utility.hpp>
 #include "../config.hh"
 #include "OverloadedCommand.hh"
 #include "ParseParameter.hh"
@@ -74,10 +75,20 @@ namespace console {
                                             1))
 #   include BOOST_PP_ITERATE()
 
+#ifndef DOXYGEN
+
     template <class Function>
     ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> &
     senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int);
 
+    template <class Owner, class Function>
+    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
+
 }}
 
 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
diff --git a/Console/ParsedCommand.mpp b/Console/ParsedCommand.mpp
index 305229017..57948c197 100644
--- a/Console/ParsedCommand.mpp
+++ b/Console/ParsedCommand.mpp
@@ -33,6 +33,7 @@
 #include <boost/preprocessor/arithmetic/inc.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>
 
 // ///////////////////////////mpp.p////////////////////////////////////////
@@ -68,9 +69,10 @@ public:
     typedef boost::function<typename traits::result_type(std::ostream &
                                                          mpp_TrailingArgTypes())> Function;
 
-#   define mpp_l(z,n,d)                                                                         \
-        typedef typename boost::remove_reference<typename traits::mpp_ArgTypeN(n)>::type        \
-            mpp_ArgTypeN(n);
+#   define mpp_l(z,n,d)                                                                           \
+        typedef typename boost::remove_const<                                                     \
+            typename boost::remove_reference< typename traits::mpp_ArgTypeN(n) >::type >::type    \
+                mpp_ArgTypeN(n);
     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
 #   undef mpp_l
 
diff --git a/Console/ParsedCommand.test.cc b/Console/ParsedCommand.test.cc
index 636560831..2b239d600 100644
--- a/Console/ParsedCommand.test.cc
+++ b/Console/ParsedCommand.test.cc
@@ -113,8 +113,55 @@ BOOST_AUTO_UNIT_TEST(parsedCommand)
                          boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )),
             senf::console::SyntaxErrorException );
     }
+
+    {
+        std::stringstream ss;
+
+        dir.add("cb", &cb1);
+        dir.add("cb", &cb5);
+        dir.add("cb", &cb2);
+        parser.parse("test/cb 111 222.4; test/cb 222; test/cb",
+                     boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 ));
+        BOOST_CHECK_EQUAL( ss.str(), "333\n" "Value: 222\n" "1.2\n" );
+    }
+}
+
+namespace {
+
+    struct Test 
+    {
+        senf::console::ScopedDirectory<Test> dir;
+        std::string name_;
+
+        Test(std::string const & name) : dir(this), name_ (name) {
+            dir.add("name", &Test::name);
+        }
+
+        std::string name(std::string const & suffix) {
+            return name_ + suffix;
+        }
+
+    };
 }
 
+BOOST_AUTO_UNIT_TEST(memberParsedCommand)
+{
+    senf::console::Executor executor;
+    senf::console::CommandParser parser;
+    senf::console::ScopedDirectory<> dir;
+    senf::console::root().add("test", dir);
+    
+    {
+        Test obj ("bar");
+        dir.add("obj", obj.dir);
+        
+        std::stringstream ss;
+        parser.parse("test/obj/name \": foo\"",
+                     boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 ));
+        BOOST_CHECK_EQUAL( ss.str(), "bar: foo\n" );
+    }
+}
+    
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
diff --git a/Console/ScopedDirectory.cti b/Console/ScopedDirectory.cti
index d1fbe7aea..04193e9b8 100644
--- a/Console/ScopedDirectory.cti
+++ b/Console/ScopedDirectory.cti
@@ -41,7 +41,7 @@ senf::console::OwnerNodeCreateTraits<Owner,Object>::Creator::create(DirectoryNod
                                                                     std::string const & name,
                                                                     Object const & ob)
 {
-    return senf_console_add_node(node, owner, name, ob);
+    return senf_console_add_node(node, owner, name, ob, 0);
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -65,7 +65,7 @@ senf::console::ScopedDirectory<Owner>::add(std::string const & name, Object cons
 template <class Owner, class Function>
 prefix_ senf::console::SimpleCommandNode & senf::console::
 senf_console_add_node(DirectoryNode & node, Owner & , std::string const & name,
-                      Function const & fn)
+                      Function const & fn, ...)
 {
     return node.add(name,fn);
 }
@@ -73,7 +73,7 @@ senf_console_add_node(DirectoryNode & node, Owner & , std::string const & name,
 template <class Owner>
 prefix_ senf::console::SimpleCommandNode & senf::console::
 senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
-                      void (Owner::*fn)(std::ostream &, ParseCommandInfo const &))
+                      void (Owner::*fn)(std::ostream &, ParseCommandInfo const &), int)
 {
     return node.add(name, boost::bind(fn,boost::ref(owner),_1,_2));
 }
diff --git a/Console/ScopedDirectory.hh b/Console/ScopedDirectory.hh
index d28e15791..e86dc59de 100644
--- a/Console/ScopedDirectory.hh
+++ b/Console/ScopedDirectory.hh
@@ -49,7 +49,8 @@ namespace console {
                                       * static_cast<DirectoryNode *>(0),
                                       * static_cast<Owner *>(0),
                                       * static_cast<std::string const *>(0),
-                                      * static_cast<Object const *>(0)) ) result_type;
+                                      * static_cast<Object const *>(0),
+                                      * static_cast<int *>(0)) ) result_type;
 
         typedef typename boost::remove_reference<result_type>::type NodeType;
 
@@ -172,12 +173,12 @@ namespace console {
 #ifndef DOXYGEN
     template <class Owner, class Function>
     SimpleCommandNode & senf_console_add_node(
-        DirectoryNode & node, Owner & owner, std::string const & name, Function const & fn);
+        DirectoryNode & node, Owner & owner, std::string const & name, Function const & fn, ...);
 
     template <class Owner>
     SimpleCommandNode & senf_console_add_node(
         DirectoryNode & node, Owner & owner, std::string const & name,
-        void (Owner::*fn)(std::ostream &, ParseCommandInfo const &));
+        void (Owner::*fn)(std::ostream &, ParseCommandInfo const &), int);
 
     template <class Node>
     DirectoryNode & senf_console_add_node(
-- 
GitLab