blob: 9902e8221bb68388b8dde8b19aab25f45d9accc8 [file] [log] [blame]
Thomas Psota79a97d62019-11-25 15:33:10 +01001#ifndef OBJ_FUNCTION_H
2#define OBJ_FUNCTION_H
3
4#include <functional>
5
Tobias Klausmannf13b5e22019-12-13 11:56:37 +01006#include <BaSyx/shared/object/object_header.h>
Thomas Psota79a97d62019-11-25 15:33:10 +01007
Tobias Klausmannf6ce45e2019-12-17 16:54:42 +01008#include <nlohmann/json.hpp>
Thomas Psota79a97d62019-11-25 15:33:10 +01009
10namespace basyx {
11namespace detail {
12
13class functionWrapper
14{
15private:
16 std::function<basyx::object(basyx::object*)> func;
17
18 template <typename R, typename... Args, std::size_t... Is>
19 static R invoke_helper(std::function<R(Args...)> f, basyx::object::object_list_t & params, util::index_sequence<Is...>)
20 {
21 return f(params[Is].Get<Args&>()...);
22 };
23public:
24 // Invoke wrapped function with no arguments
Johannes Wendeled007a12019-11-25 17:09:45 +010025 basyx::object invoke() const
Thomas Psota79a97d62019-11-25 15:33:10 +010026 {
27 return func(nullptr);
28 };
29
30 // Invoke wrapped function with argument
31 // Has to be primitive object or object list
Johannes Wendeled007a12019-11-25 17:09:45 +010032 basyx::object invoke(basyx::object & obj) const
Thomas Psota79a97d62019-11-25 15:33:10 +010033 {
34 return func(&obj);
35 };
36
37 // Wrap function with no arguments
38 template<typename RetType>
39 static functionWrapper wrap_func(std::function<RetType(void)> f)
40 {
41 functionWrapper fw;
42 fw.func = [f](basyx::object*)
43 {
44 return basyx::object{ f() };
45 };
46 return fw;
47 };
48
49 // Wrap function with single argument
50 template<typename RetType, typename Arg>
51 static functionWrapper wrap_func(std::function<RetType(Arg)> f)
52 {
53 functionWrapper fw;
54 fw.func = [f](basyx::object * obj)
55 {
56 // Only allow primitive object types
57 if (obj != nullptr && obj->GetObjectType() == basyx::type::objectType::Primitive && obj->GetValueType() == basyx::type::basyx_type<Arg>::value_type)
58 {
59 // Cast object to argument type and invoke
60 auto & i = obj->Get<Arg&>();
61 return basyx::object{ f(i) };
62 };
63
64 return basyx::object::make_null();
65 };
66 return fw;
67 };
68
69 // Wrap function with argument list
70 template<typename RetType, typename... Args>
71 static functionWrapper wrap_func(std::function<RetType(Args...)> f)
72 {
73 functionWrapper fw;
74 fw.func = [f](basyx::object * obj)
75 {
76 // Only allow object lists
77 if (obj != nullptr && obj->GetObjectType() == basyx::type::objectType::List && obj->GetValueType() == basyx::type::valueType::Object)
78 {
79 auto & list = obj->Get<basyx::object::object_list_t&>();
80
81 // if size of argument list differs from the functions parameter list, return null
82 if (list.size() != sizeof...(Args))
83 return basyx::object::make_null();
84
85 // TODO: type check arguments
86
87 // Invoke, using an integer sequence to pass the values from the list as single parameters to the function
88 return basyx::object{ invoke_helper<RetType, Args...>(f, list, util::make_index_sequence<sizeof...(Args)>{}) };
89 };
90
91 return basyx::object::make_null();
92 };
93 return fw;
94 };
95
96 template<typename T>
97 bool operator==(const T &) const
98 {
99 return false;
100 };
101};
102
103static void to_json(nlohmann::json & json, const functionWrapper &)
104{
105 return;
106};
107
108}
109}
110
111
112#endif /* OBJ_FUNCTION_H */