summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/gras/callable.hpp37
-rw-r--r--include/gras/detail/callable.hpp255
-rw-r--r--lib/callable.cpp2
-rw-r--r--tests/callable_test.cpp109
4 files changed, 322 insertions, 81 deletions
diff --git a/include/gras/callable.hpp b/include/gras/callable.hpp
index 6b2a3b6..32d6d17 100644
--- a/include/gras/callable.hpp
+++ b/include/gras/callable.hpp
@@ -39,46 +39,59 @@ struct GRAS_API Callable
template <typename ClassType, typename ReturnType>
void register_call(const std::string &key, ReturnType(ClassType::*fcn)(void));
- template <typename ClassType, typename ReturnType, typename Arg0>
- void register_call(const std::string &key, ReturnType(ClassType::*fcn)(const Arg0 &));
-
- template <typename ClassType, typename ReturnType, typename Arg0, typename Arg1>
- void register_call(const std::string &key, ReturnType(ClassType::*fcn)(const Arg0 &, const Arg1 &));
-
template <typename ClassType>
void register_call(const std::string &key, void(ClassType::*fcn)(void));
+ template <typename ClassType, typename ReturnType, typename Arg0>
+ void register_call(const std::string &key, ReturnType(ClassType::*fcn)(const Arg0 &));
+
template <typename ClassType, typename Arg0>
void register_call(const std::string &key, void(ClassType::*fcn)(const Arg0 &));
+ template <typename ClassType, typename ReturnType, typename Arg0, typename Arg1>
+ void register_call(const std::string &key, ReturnType(ClassType::*fcn)(const Arg0 &, const Arg1 &));
+
template <typename ClassType, typename Arg0, typename Arg1>
void register_call(const std::string &key, void(ClassType::*fcn)(const Arg0 &, const Arg1 &));
+ template <typename ClassType, typename ReturnType, typename Arg0, typename Arg1, typename Arg2>
+ void register_call(const std::string &key, ReturnType(ClassType::*fcn)(const Arg0 &, const Arg1 &, const Arg2 &));
+
+ template <typename ClassType, typename Arg0, typename Arg1, typename Arg2>
+ void register_call(const std::string &key, void(ClassType::*fcn)(const Arg0 &, const Arg1 &, const Arg2 &));
+
/*******************************************************************
* Call API - don't look here, template magic, not helpful
******************************************************************/
template <typename ReturnType>
ReturnType call(const std::string &key);
+ inline
+ void call(const std::string &key);
+
template <typename ReturnType, typename Arg0>
ReturnType call(const std::string &key, const Arg0 &);
- template <typename ReturnType, typename Arg0, typename Arg1>
- ReturnType call(const std::string &key, const Arg0 &, const Arg1 &);
-
- void call(const std::string &key);
-
template <typename Arg0>
void call(const std::string &key, const Arg0 &);
+ template <typename ReturnType, typename Arg0, typename Arg1>
+ ReturnType call(const std::string &key, const Arg0 &, const Arg1 &);
+
template <typename Arg0, typename Arg1>
void call(const std::string &key, const Arg0 &, const Arg1 &);
+ template <typename ReturnType, typename Arg0, typename Arg1, typename Arg2>
+ ReturnType call(const std::string &key, const Arg0 &, const Arg1 &, const Arg2 &);
+
+ template <typename Arg0, typename Arg1, typename Arg2>
+ void call(const std::string &key, const Arg0 &, const Arg1 &, const Arg2 &);
+
/*******************************************************************
* Private registration hooks
******************************************************************/
void _register_call(const std::string &, void *);
- virtual PMCC _handle_call(const std::string &, const std::vector<PMCC> &);
+ virtual PMCC _handle_call(const std::string &, const PMCC *);
void *_call_registry;
};
diff --git a/include/gras/detail/callable.hpp b/include/gras/detail/callable.hpp
index 5e7854a..23e3ab6 100644
--- a/include/gras/detail/callable.hpp
+++ b/include/gras/detail/callable.hpp
@@ -8,112 +8,277 @@
namespace gras
{
+/***********************************************************************
+ * Registration entry base class
+ **********************************************************************/
struct GRAS_API CallableRegistryEntry
{
CallableRegistryEntry(void);
virtual ~CallableRegistryEntry(void);
- virtual PMCC call(const std::vector<PMCC> &args) = 0;
+ virtual PMCC call(const PMCC *args) = 0;
};
-template <typename ClassType, typename ReturnType, typename Arg0, typename Arg1>
-class CallableRegistryEntryImpl : public CallableRegistryEntry
+/***********************************************************************
+ * Registration for return with 0 args
+ **********************************************************************/
+template <typename ClassType, typename ReturnType>
+struct CallableRegistryEntryImpl0 : CallableRegistryEntry
{
-public:
-
- typedef ReturnType(ClassType::*Fcn0)(void);
- typedef ReturnType(ClassType::*Fcn1)(const Arg0 &);
- typedef ReturnType(ClassType::*Fcn2)(const Arg0 &, const Arg1 &);
-
- CallableRegistryEntryImpl(ClassType *obj, Fcn0 fcn0, Fcn1 fcn1 = NULL, Fcn2 fcn2 = NULL):
- _obj(obj), _fcn0(fcn0), _fcn1(fcn1), _fcn2(fcn2)
- {}
- virtual ~CallableRegistryEntryImpl(void){}
-
- PMCC call(const std::vector<PMCC> &args)
+ typedef ReturnType(ClassType::*Fcn)(void);
+ CallableRegistryEntryImpl0(ClassType *obj, Fcn fcn):
+ _obj(obj), _fcn(fcn){}
+ PMCC call(const PMCC *args)
{
- if (_fcn0) return PMC_M((_obj->*_fcn0)());
- if (_fcn1) return PMC_M((_obj->*_fcn1)(args[0].safe_as<Arg0>()));
- if (_fcn2) return PMC_M((_obj->*_fcn2)(args[0].safe_as<Arg0>(), args[1].safe_as<Arg1>()));
- return PMCC();//should not get here
+ return PMC_M((_obj->*_fcn)());
}
-
-private:
- ClassType *_obj;
- Fcn0 _fcn0; Fcn1 _fcn1; Fcn2 _fcn2;
+ ClassType *_obj; Fcn _fcn;
};
template <typename ClassType, typename ReturnType>
void Callable::register_call(const std::string &key, ReturnType(ClassType::*fcn)(void))
{
ClassType *obj = dynamic_cast<ClassType *>(this);
- void *fr = new CallableRegistryEntryImpl<ClassType, ReturnType, int, int>(obj, fcn);
+ void *fr = new CallableRegistryEntryImpl0<ClassType, ReturnType>(obj, fcn);
_register_call(key, fr);
}
+template <typename ClassType>
+struct CallableRegistryEntryImplVoid0 : CallableRegistryEntry
+{
+ typedef void(ClassType::*Fcn)(void);
+ CallableRegistryEntryImplVoid0(ClassType *obj, Fcn fcn):
+ _obj(obj), _fcn(fcn){}
+ PMCC call(const PMCC *args)
+ {
+ (_obj->*_fcn)(); return PMCC();
+ }
+ ClassType *_obj; Fcn _fcn;
+};
+
+template <typename ClassType>
+void Callable::register_call(const std::string &key, void(ClassType::*fcn)(void))
+{
+ ClassType *obj = dynamic_cast<ClassType *>(this);
+ void *fr = new CallableRegistryEntryImplVoid0<ClassType>(obj, fcn);
+ _register_call(key, fr);
+}
+
+/***********************************************************************
+ * Registration for return with 1 args
+ **********************************************************************/
+template <typename ClassType, typename ReturnType, typename Arg0>
+struct CallableRegistryEntryImpl1 : CallableRegistryEntry
+{
+ typedef ReturnType(ClassType::*Fcn)(const Arg0 &);
+ CallableRegistryEntryImpl1(ClassType *obj, Fcn fcn):
+ _obj(obj), _fcn(fcn){}
+ PMCC call(const PMCC *args)
+ {
+ return PMC_M((_obj->*_fcn)(args[0].safe_as<Arg0>()));
+ }
+ ClassType *_obj; Fcn _fcn;
+};
+
template <typename ClassType, typename ReturnType, typename Arg0>
void Callable::register_call(const std::string &key, ReturnType(ClassType::*fcn)(const Arg0 &))
{
ClassType *obj = dynamic_cast<ClassType *>(this);
- void *fr = new CallableRegistryEntryImpl<ClassType, ReturnType, Arg0, int>(obj, NULL, fcn);
+ void *fr = new CallableRegistryEntryImpl1<ClassType, ReturnType, Arg0>(obj, fcn);
+ _register_call(key, fr);
+}
+
+template <typename ClassType, typename Arg0>
+struct CallableRegistryEntryImplVoid1 : CallableRegistryEntry
+{
+ typedef void(ClassType::*Fcn)(const Arg0 &);
+ CallableRegistryEntryImplVoid1(ClassType *obj, Fcn fcn):
+ _obj(obj), _fcn(fcn){}
+ PMCC call(const PMCC *args)
+ {
+ (_obj->*_fcn)(args[0].safe_as<Arg0>()); return PMCC();
+ }
+ ClassType *_obj; Fcn _fcn;
+};
+
+template <typename ClassType, typename Arg0>
+void Callable::register_call(const std::string &key, void(ClassType::*fcn)(const Arg0 &))
+{
+ ClassType *obj = dynamic_cast<ClassType *>(this);
+ void *fr = new CallableRegistryEntryImplVoid1<ClassType, Arg0>(obj, fcn);
_register_call(key, fr);
}
+/***********************************************************************
+ * Registration for return with 2 args
+ **********************************************************************/
+template <typename ClassType, typename ReturnType, typename Arg0, typename Arg1>
+struct CallableRegistryEntryImpl2 : CallableRegistryEntry
+{
+ typedef ReturnType(ClassType::*Fcn)(const Arg0 &, const Arg1 &);
+ CallableRegistryEntryImpl2(ClassType *obj, Fcn fcn):
+ _obj(obj), _fcn(fcn){}
+ PMCC call(const PMCC *args)
+ {
+ return PMC_M((_obj->*_fcn)(args[0].safe_as<Arg0>(), args[1].safe_as<Arg1>()));
+ }
+ ClassType *_obj; Fcn _fcn;
+};
+
template <typename ClassType, typename ReturnType, typename Arg0, typename Arg1>
void Callable::register_call(const std::string &key, ReturnType(ClassType::*fcn)(const Arg0 &, const Arg1 &))
{
ClassType *obj = dynamic_cast<ClassType *>(this);
- void *fr = new CallableRegistryEntryImpl<ClassType, ReturnType, Arg0, Arg1>(obj, NULL, NULL, fcn);
+ void *fr = new CallableRegistryEntryImpl2<ClassType, ReturnType, Arg0, Arg1>(obj, fcn);
_register_call(key, fr);
}
+template <typename ClassType, typename Arg0, typename Arg1>
+struct CallableRegistryEntryImplVoid2 : CallableRegistryEntry
+{
+ typedef void(ClassType::*Fcn)(const Arg0 &, const Arg1 &);
+ CallableRegistryEntryImplVoid2(ClassType *obj, Fcn fcn):
+ _obj(obj), _fcn(fcn){}
+ PMCC call(const PMCC *args)
+ {
+ (_obj->*_fcn)(args[0].safe_as<Arg0>(), args[1].safe_as<Arg1>()); return PMCC();
+ }
+ ClassType *_obj; Fcn _fcn;
+};
+
+template <typename ClassType, typename Arg0, typename Arg1>
+void Callable::register_call(const std::string &key, void(ClassType::*fcn)(const Arg0 &, const Arg1 &))
+{
+ ClassType *obj = dynamic_cast<ClassType *>(this);
+ void *fr = new CallableRegistryEntryImplVoid2<ClassType, Arg0, Arg1>(obj, fcn);
+ _register_call(key, fr);
+}
+
+/***********************************************************************
+ * Registration for return with 3 args
+ **********************************************************************/
+template <typename ClassType, typename ReturnType, typename Arg0, typename Arg1, typename Arg2>
+struct CallableRegistryEntryImpl3 : CallableRegistryEntry
+{
+ typedef ReturnType(ClassType::*Fcn)(const Arg0 &, const Arg1 &, const Arg2 &);
+ CallableRegistryEntryImpl3(ClassType *obj, Fcn fcn):
+ _obj(obj), _fcn(fcn){}
+ PMCC call(const PMCC *args)
+ {
+ return PMC_M((_obj->*_fcn)(args[0].safe_as<Arg0>(), args[1].safe_as<Arg1>(), args[2].safe_as<Arg2>()));
+ }
+ ClassType *_obj; Fcn _fcn;
+};
+
+template <typename ClassType, typename ReturnType, typename Arg0, typename Arg1, typename Arg2>
+void Callable::register_call(const std::string &key, ReturnType(ClassType::*fcn)(const Arg0 &, const Arg1 &, const Arg2 &))
+{
+ ClassType *obj = dynamic_cast<ClassType *>(this);
+ void *fr = new CallableRegistryEntryImpl3<ClassType, ReturnType, Arg0, Arg1, Arg2>(obj, fcn);
+ _register_call(key, fr);
+}
+
+template <typename ClassType, typename Arg0, typename Arg1, typename Arg2>
+struct CallableRegistryEntryImplVoid3 : CallableRegistryEntry
+{
+ typedef void(ClassType::*Fcn)(const Arg0 &, const Arg1 &, const Arg2 &);
+ CallableRegistryEntryImplVoid3(ClassType *obj, Fcn fcn):
+ _obj(obj), _fcn(fcn){}
+ PMCC call(const PMCC *args)
+ {
+ (_obj->*_fcn)(args[0].safe_as<Arg0>(), args[1].safe_as<Arg1>(), args[2].safe_as<Arg2>()); return PMCC();
+ }
+ ClassType *_obj; Fcn _fcn;
+};
+
+template <typename ClassType, typename Arg0, typename Arg1, typename Arg2>
+void Callable::register_call(const std::string &key, void(ClassType::*fcn)(const Arg0 &, const Arg1 &, const Arg2 &))
+{
+ ClassType *obj = dynamic_cast<ClassType *>(this);
+ void *fr = new CallableRegistryEntryImplVoid3<ClassType, Arg0, Arg1, Arg2>(obj, fcn);
+ _register_call(key, fr);
+}
+
+/***********************************************************************
+ * Call implementations with 0 args
+ **********************************************************************/
template <typename ReturnType>
ReturnType Callable::call(const std::string &key)
{
- std::vector<PMCC> args;
+ PMCC args[0];
PMCC r = _handle_call(key, args);
return r.safe_as<ReturnType>();
}
+inline
+void Callable::call(const std::string &key)
+{
+ PMCC args[0];
+ _handle_call(key, args);
+}
+
+/***********************************************************************
+ * Call implementations with 1 args
+ **********************************************************************/
template <typename ReturnType, typename Arg0>
ReturnType Callable::call(const std::string &key, const Arg0 &a0)
{
- std::vector<PMCC> args;
- args.push_back(PMC_M(a0));
+ PMCC args[1];
+ args[0] = PMC_M(a0);
PMCC r = _handle_call(key, args);
return r.safe_as<ReturnType>();
}
+template <typename Arg0>
+void Callable::call(const std::string &key, const Arg0 &a0)
+{
+ PMCC args[1];
+ args[0] = PMC_M(a0);
+ _handle_call(key, args);
+}
+
+/***********************************************************************
+ * Call implementations with 2 args
+ **********************************************************************/
template <typename ReturnType, typename Arg0, typename Arg1>
ReturnType Callable::call(const std::string &key, const Arg0 &a0, const Arg1 &a1)
{
- std::vector<PMCC> args;
- args.push_back(PMC_M(a0));
- args.push_back(PMC_M(a1));
+ PMCC args[2];
+ args[0] = PMC_M(a0);
+ args[1] = PMC_M(a1);
PMCC r = _handle_call(key, args);
return r.safe_as<ReturnType>();
}
-inline
-void Callable::call(const std::string &key)
+template <typename Arg0, typename Arg1>
+void Callable::call(const std::string &key, const Arg0 &a0, const Arg1 &a1)
{
- std::vector<PMCC> args;
+ PMCC args[2];
+ args[0] = PMC_M(a0);
+ args[1] = PMC_M(a1);
_handle_call(key, args);
}
-template <typename Arg0>
-void Callable::call(const std::string &key, const Arg0 &a0)
+/***********************************************************************
+ * Call implementations with 3 args
+ **********************************************************************/
+template <typename ReturnType, typename Arg0, typename Arg1, typename Arg2>
+ReturnType Callable::call(const std::string &key, const Arg0 &a0, const Arg1 &a1, const Arg2 &a2)
{
- std::vector<PMCC> args;
- args.push_back(PMC_M(a0));
- _handle_call(key, args);
+ PMCC args[3];
+ args[0] = PMC_M(a0);
+ args[1] = PMC_M(a1);
+ args[2] = PMC_M(a2);
+ PMCC r = _handle_call(key, args);
+ return r.safe_as<ReturnType>();
}
-template <typename Arg0, typename Arg1>
-void Callable::call(const std::string &key, const Arg0 &a0, const Arg1 &a1)
+template <typename Arg0, typename Arg1, typename Arg2>
+void Callable::call(const std::string &key, const Arg0 &a0, const Arg1 &a1, const Arg2 &a2)
{
- std::vector<PMCC> args;
- args.push_back(PMC_M(a0));
- args.push_back(PMC_M(a1));
+ PMCC args[3];
+ args[0] = PMC_M(a0);
+ args[1] = PMC_M(a1);
+ args[2] = PMC_M(a2);
_handle_call(key, args);
}
diff --git a/lib/callable.cpp b/lib/callable.cpp
index a6417bb..6014974 100644
--- a/lib/callable.cpp
+++ b/lib/callable.cpp
@@ -26,7 +26,7 @@ void Callable::_register_call(const std::string &key, void *entry)
(*cr)[key].reset(reinterpret_cast<CallableRegistryEntry *>(entry));
}
-PMCC Callable::_handle_call(const std::string &key, const std::vector<PMCC> &args)
+PMCC Callable::_handle_call(const std::string &key, const PMCC *args)
{
CallableRegistry *cr = reinterpret_cast<CallableRegistry *>(_call_registry);
boost::shared_ptr<CallableRegistryEntry> entry = (*cr)[key];
diff --git a/tests/callable_test.cpp b/tests/callable_test.cpp
index 1753f79..684a820 100644
--- a/tests/callable_test.cpp
+++ b/tests/callable_test.cpp
@@ -10,44 +10,107 @@ struct MyClass : gras::Callable
{
MyClass(void)
{
- this->register_call("foo", &MyClass::foo);
- this->register_call("bar", &MyClass::bar);
- this->register_call("baz", &MyClass::baz);
- //this->register_call("example_setter", &MyClass::example_setter);
+ count = 0;
+ this->register_call("test_args0_with_return", &MyClass::test_args0_with_return);
+ this->register_call("test_args1_with_return", &MyClass::test_args1_with_return);
+ this->register_call("test_args2_with_return", &MyClass::test_args2_with_return);
+ this->register_call("test_args3_with_return", &MyClass::test_args3_with_return);
+ this->register_call("test_args0_with_no_return", &MyClass::test_args0_with_no_return);
+ this->register_call("test_args1_with_no_return", &MyClass::test_args1_with_no_return);
+ this->register_call("test_args2_with_no_return", &MyClass::test_args2_with_no_return);
+ this->register_call("test_args3_with_no_return", &MyClass::test_args3_with_no_return);
}
- int foo(void)
+ int test_args0_with_return(void)
{
- return 42;
+ return count;
}
- int bar(const std::string &a0)
+ int test_args1_with_return(const int &a0)
{
- return a0.size();
+ return a0;
}
- int baz(const std::string &a0, const bool &a1)
+ int test_args2_with_return(const int &a0, const std::string &a1)
{
- return a1?a0.size():-1;
+ return a0 + a1.size();
}
- void example_setter(const long &)
+ int test_args3_with_return(const int &a0, const std::string &a1, const bool &a3)
{
-
+ return a3? a0 + a1.size() : 0;
}
-};
-BOOST_AUTO_TEST_CASE(test_property_newshit)
-{
- MyClass my_class;
- size_t my_foo = my_class.call<size_t>("foo");
- BOOST_CHECK_EQUAL(my_foo, size_t(42));
+ void test_args0_with_no_return(void)
+ {
+ count++;
+ }
+
+ void test_args1_with_no_return(const int &a0)
+ {
+ count = a0;
+ }
+
+ void test_args2_with_no_return(const int &a0, const std::string &a1)
+ {
+ count = a0 + a1.size();
+ }
- size_t my_bar = my_class.call<size_t>("bar", "hello");
- BOOST_CHECK_EQUAL(my_bar, size_t(5));
+ void test_args3_with_no_return(const int &a0, const std::string &a1, const bool &a2)
+ {
+ if (a2) count = a0 + a1.size();
+ else count = 0;
+ }
- signed my_baz = my_class.call<signed>("baz", "hello", false);
- BOOST_CHECK_EQUAL(my_baz, signed(-1));
+ int count;
+};
- //my_class.call("example_setter", 123);
+BOOST_AUTO_TEST_CASE(test_registered_methods)
+{
+ MyClass my_class;
+ {
+ size_t ret = my_class.call<size_t>("test_args0_with_return");
+ BOOST_CHECK_EQUAL(ret, size_t(0));
+ }
+ {
+ size_t ret = my_class.call<size_t>("test_args1_with_return", 42);
+ BOOST_CHECK_EQUAL(ret, size_t(42));
+ }
+ {
+ size_t ret = my_class.call<size_t>("test_args2_with_return", 1, "OK");
+ BOOST_CHECK_EQUAL(ret, size_t(3));
+ }
+ {
+ size_t ret = my_class.call<size_t>("test_args3_with_return", 1, "OK", true);
+ BOOST_CHECK_EQUAL(ret, size_t(3));
+ }
+ {
+ size_t ret = my_class.call<size_t>("test_args3_with_return", 1, "OK", false);
+ BOOST_CHECK_EQUAL(ret, size_t(0));
+ }
+ {
+ my_class.call("test_args0_with_no_return"); //this adds 1 to count
+ size_t ret = my_class.call<size_t>("test_args0_with_return");
+ BOOST_CHECK_EQUAL(ret, size_t(1));
+ }
+ {
+ my_class.call("test_args1_with_no_return", 42);
+ size_t ret = my_class.call<size_t>("test_args0_with_return");
+ BOOST_CHECK_EQUAL(ret, size_t(42));
+ }
+ {
+ my_class.call("test_args2_with_no_return", 1, "OK");
+ size_t ret = my_class.call<size_t>("test_args0_with_return");
+ BOOST_CHECK_EQUAL(ret, size_t(3));
+ }
+ {
+ my_class.call("test_args3_with_no_return", 1, "OK", true);
+ size_t ret = my_class.call<size_t>("test_args0_with_return");
+ BOOST_CHECK_EQUAL(ret, size_t(3));
+ }
+ {
+ my_class.call("test_args3_with_no_return", 1, "OK", false);
+ size_t ret = my_class.call<size_t>("test_args0_with_return");
+ BOOST_CHECK_EQUAL(ret, size_t(0));
+ }
}