Complete refactor of basyx::vab and basyx::shared in C++ sdk, introducing new object type system basyx::object

Change-Id: I0058ddcb07c5005dc40e3c81b648efe7621c3121
Signed-off-by: Thomas Psota <thomas.psota@iese.fraunhofer.de>
diff --git a/sdks/c++/basys.sdk.cc/src/shared/basyx/object/obj_function.h b/sdks/c++/basys.sdk.cc/src/shared/basyx/object/obj_function.h
new file mode 100644
index 0000000..48c81f8
--- /dev/null
+++ b/sdks/c++/basys.sdk.cc/src/shared/basyx/object/obj_function.h
@@ -0,0 +1,112 @@
+#ifndef OBJ_FUNCTION_H
+#define OBJ_FUNCTION_H
+
+#include <functional>
+
+#include <basyx/object/object_header.h>
+
+#include <json/json.hpp>
+
+namespace basyx {
+namespace detail {
+
+class functionWrapper
+{
+private:
+	std::function<basyx::object(basyx::object*)> func;
+
+	template <typename R, typename... Args, std::size_t... Is>
+	static R invoke_helper(std::function<R(Args...)> f, basyx::object::object_list_t & params, util::index_sequence<Is...>)
+	{
+		return f(params[Is].Get<Args&>()...);
+	};
+public:
+	// Invoke wrapped function with no arguments
+	basyx::object invoke()
+	{
+		return func(nullptr);
+	};
+
+	// Invoke wrapped function with argument
+	// Has to be primitive object or object list
+	basyx::object invoke(basyx::object & obj)
+	{
+		return func(&obj);
+	};
+
+	// Wrap function with no arguments
+	template<typename RetType>
+	static functionWrapper wrap_func(std::function<RetType(void)> f)
+	{
+		functionWrapper fw;
+		fw.func = [f](basyx::object*)
+		{
+			return basyx::object{ f() };
+		};
+		return fw;
+	};
+
+	// Wrap function with single argument
+	template<typename RetType, typename Arg>
+	static functionWrapper wrap_func(std::function<RetType(Arg)> f)
+	{
+		functionWrapper fw;
+		fw.func = [f](basyx::object * obj)
+		{
+			// Only allow primitive object types
+			if (obj != nullptr && obj->GetObjectType() == basyx::type::objectType::Primitive && obj->GetValueType() == basyx::type::basyx_type<Arg>::value_type)
+			{
+				// Cast object to argument type and invoke
+				auto & i = obj->Get<Arg&>();
+				return basyx::object{ f(i) };
+			};
+
+			return basyx::object::make_null();
+		};
+		return fw;
+	};
+
+	// Wrap function with argument list
+	template<typename RetType, typename... Args>
+	static functionWrapper wrap_func(std::function<RetType(Args...)> f)
+	{
+		functionWrapper fw;
+		fw.func = [f](basyx::object * obj)
+		{
+			// Only allow object lists
+			if (obj != nullptr && obj->GetObjectType() == basyx::type::objectType::List && obj->GetValueType() == basyx::type::valueType::Object)
+			{
+				auto & list = obj->Get<basyx::object::object_list_t&>();
+
+				// if size of argument list differs from the functions parameter list, return null
+				if (list.size() != sizeof...(Args))
+					return basyx::object::make_null();
+
+				// TODO: type check arguments
+
+				// Invoke, using an integer sequence to pass the values from the list as single parameters to the function
+				return basyx::object{ invoke_helper<RetType, Args...>(f, list, util::make_index_sequence<sizeof...(Args)>{}) };
+			};
+
+			return basyx::object::make_null();
+		};
+		return fw;
+	};
+
+	template<typename T>
+	bool operator==(const T &) const
+	{
+		return false;
+	};
+};
+
+static void to_json(nlohmann::json & json, const functionWrapper &)
+{
+	return;
+};
+
+}
+}
+
+
+#endif /* OBJ_FUNCTION_H */