summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/gras/callable.hpp2
-rw-r--r--include/gras/detail/callable.hpp45
-rw-r--r--lib/CMakeLists.txt1
-rw-r--r--lib/callable.cpp45
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/callable_test.cpp53
6 files changed, 128 insertions, 19 deletions
diff --git a/include/gras/callable.hpp b/include/gras/callable.hpp
index 07c6034..6b2a3b6 100644
--- a/include/gras/callable.hpp
+++ b/include/gras/callable.hpp
@@ -79,7 +79,7 @@ struct GRAS_API Callable
******************************************************************/
void _register_call(const std::string &, void *);
virtual PMCC _handle_call(const std::string &, const std::vector<PMCC> &);
- std::map<std::string, void *> _call_registry;
+ void *_call_registry;
};
} //namespace gras
diff --git a/include/gras/detail/callable.hpp b/include/gras/detail/callable.hpp
index 86b741d..5e7854a 100644
--- a/include/gras/detail/callable.hpp
+++ b/include/gras/detail/callable.hpp
@@ -8,15 +8,15 @@
namespace gras
{
-struct GRAS_API CallableRegistry
+struct GRAS_API CallableRegistryEntry
{
- CallableRegistry(void);
- virtual ~CallableRegistry(void);
+ CallableRegistryEntry(void);
+ virtual ~CallableRegistryEntry(void);
virtual PMCC call(const std::vector<PMCC> &args) = 0;
};
template <typename ClassType, typename ReturnType, typename Arg0, typename Arg1>
-class CallableRegistryImpl : public CallableRegistry
+class CallableRegistryEntryImpl : public CallableRegistryEntry
{
public:
@@ -24,10 +24,10 @@ public:
typedef ReturnType(ClassType::*Fcn1)(const Arg0 &);
typedef ReturnType(ClassType::*Fcn2)(const Arg0 &, const Arg1 &);
- CallableRegistryImpl(ClassType *obj, Fcn0 fcn0, Fcn1 fcn1 = NULL, Fcn2 fcn2 = NULL):
+ CallableRegistryEntryImpl(ClassType *obj, Fcn0 fcn0, Fcn1 fcn1 = NULL, Fcn2 fcn2 = NULL):
_obj(obj), _fcn0(fcn0), _fcn1(fcn1), _fcn2(fcn2)
{}
- virtual ~CallableRegistryImpl(void){}
+ virtual ~CallableRegistryEntryImpl(void){}
PMCC call(const std::vector<PMCC> &args)
{
@@ -42,35 +42,40 @@ private:
Fcn0 _fcn0; Fcn1 _fcn1; Fcn2 _fcn2;
};
-template <typename ClassType, typename ReturnType> void Callable::register_call(const std::string &key, ReturnType(ClassType::*fcn)(void))
+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 CallableRegistryImpl<ClassType, ReturnType, int, int>(obj, fcn);
+ void *fr = new CallableRegistryEntryImpl<ClassType, ReturnType, int, int>(obj, fcn);
_register_call(key, fr);
}
-template <typename ClassType, typename ReturnType, typename Arg0> void Callable::register_call(const std::string &key, ReturnType(ClassType::*fcn)(const Arg0 &))
+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 CallableRegistryImpl<ClassType, ReturnType, Arg0, int>(obj, NULL, fcn);
+ void *fr = new CallableRegistryEntryImpl<ClassType, ReturnType, Arg0, int>(obj, NULL, fcn);
_register_call(key, fr);
}
-template <typename ClassType, typename ReturnType, typename Arg0, typename Arg1> void Callable::register_call(const std::string &key, ReturnType(ClassType::*fcn)(const Arg0 &, const Arg1 &))
+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 CallableRegistryImpl<ClassType, ReturnType, Arg0, Arg1>(obj, NULL, NULL, fcn);
+ void *fr = new CallableRegistryEntryImpl<ClassType, ReturnType, Arg0, Arg1>(obj, NULL, NULL, fcn);
_register_call(key, fr);
}
-template <typename ReturnType> ReturnType Callable::call(const std::string &key)
+template <typename ReturnType>
+ReturnType Callable::call(const std::string &key)
{
std::vector<PMCC> args;
PMCC r = _handle_call(key, args);
return r.safe_as<ReturnType>();
}
-template <typename ReturnType, typename Arg0> ReturnType Callable::call(const std::string &key, const Arg0 &a0)
+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));
@@ -78,7 +83,8 @@ template <typename ReturnType, typename Arg0> ReturnType Callable::call(const st
return r.safe_as<ReturnType>();
}
-template <typename ReturnType, typename Arg0, typename Arg1> ReturnType Callable::call(const std::string &key, const Arg0 &a0, const Arg1 &a1)
+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));
@@ -87,20 +93,23 @@ template <typename ReturnType, typename Arg0, typename Arg1> ReturnType Callable
return r.safe_as<ReturnType>();
}
-inline void Callable::call(const std::string &key)
+inline
+void Callable::call(const std::string &key)
{
std::vector<PMCC> args;
_handle_call(key, args);
}
-template <typename Arg0> void Callable::call(const std::string &key, const Arg0 &a0)
+template <typename Arg0>
+void Callable::call(const std::string &key, const Arg0 &a0)
{
std::vector<PMCC> args;
args.push_back(PMC_M(a0));
_handle_call(key, args);
}
-template <typename Arg0, typename Arg1> void Callable::call(const std::string &key, const Arg0 &a0, const Arg1 &a1)
+template <typename Arg0, typename Arg1>
+void Callable::call(const std::string &key, const Arg0 &a0, const Arg1 &a1)
{
std::vector<PMCC> args;
args.push_back(PMC_M(a0));
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index ab5d886..38216b3 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -41,6 +41,7 @@ list(APPEND GRAS_SOURCES ${apology_sources})
########################################################################
list(APPEND GRAS_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/debug.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/callable.cpp
${CMAKE_CURRENT_SOURCE_DIR}/element.cpp
${CMAKE_CURRENT_SOURCE_DIR}/element_uid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/sbuffer.cpp
diff --git a/lib/callable.cpp b/lib/callable.cpp
new file mode 100644
index 0000000..a6417bb
--- /dev/null
+++ b/lib/callable.cpp
@@ -0,0 +1,45 @@
+// Copyright (C) by Josh Blum. See LICENSE.txt for licensing information.
+
+#include <gras/callable.hpp>
+#include <boost/shared_ptr.hpp>
+#include <stdexcept>
+#include <map>
+
+using namespace gras;
+
+typedef std::map<std::string, boost::shared_ptr<CallableRegistryEntry> > CallableRegistry;
+
+Callable::Callable(void)
+{
+ _call_registry = new CallableRegistry();
+}
+
+Callable::~Callable(void)
+{
+ CallableRegistry *cr = reinterpret_cast<CallableRegistry *>(_call_registry);
+ delete cr;
+}
+
+void Callable::_register_call(const std::string &key, void *entry)
+{
+ CallableRegistry *cr = reinterpret_cast<CallableRegistry *>(_call_registry);
+ (*cr)[key].reset(reinterpret_cast<CallableRegistryEntry *>(entry));
+}
+
+PMCC Callable::_handle_call(const std::string &key, const std::vector<PMCC> &args)
+{
+ CallableRegistry *cr = reinterpret_cast<CallableRegistry *>(_call_registry);
+ boost::shared_ptr<CallableRegistryEntry> entry = (*cr)[key];
+ if (not entry) throw std::invalid_argument("Callable: no method registered for key: " + key);
+ return entry->call(args);
+}
+
+CallableRegistryEntry::CallableRegistryEntry(void)
+{
+ //NOP
+}
+
+CallableRegistryEntry::~CallableRegistryEntry(void)
+{
+ //NOP
+}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index bc3815e..bb3f3c8 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -14,6 +14,7 @@ if (NOT Boost_FOUND)
endif()
set(test_sources
+ callable_test.cpp
chrono_time_test.cpp
block_props_test.cpp
serialize_tags_test.cpp
diff --git a/tests/callable_test.cpp b/tests/callable_test.cpp
new file mode 100644
index 0000000..1753f79
--- /dev/null
+++ b/tests/callable_test.cpp
@@ -0,0 +1,53 @@
+// Copyright (C) by Josh Blum. See LICENSE.txt for licensing information.
+
+#include <boost/test/unit_test.hpp>
+#include <iostream>
+
+#include <gras/callable.hpp>
+
+
+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);
+ }
+
+ int foo(void)
+ {
+ return 42;
+ }
+
+ int bar(const std::string &a0)
+ {
+ return a0.size();
+ }
+
+ int baz(const std::string &a0, const bool &a1)
+ {
+ return a1?a0.size():-1;
+ }
+
+ void example_setter(const long &)
+ {
+
+ }
+};
+
+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));
+
+ size_t my_bar = my_class.call<size_t>("bar", "hello");
+ BOOST_CHECK_EQUAL(my_bar, size_t(5));
+
+ signed my_baz = my_class.call<signed>("baz", "hello", false);
+ BOOST_CHECK_EQUAL(my_baz, signed(-1));
+
+ //my_class.call("example_setter", 123);
+}