From 56ae875861ab260b80a030f50c4aff9f9dc8fff0 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 13 Apr 2024 13:32:39 +0200 Subject: Adding upstream version 2.14.2. Signed-off-by: Daniel Baumann --- lib/base/functionwrapper.hpp | 149 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 lib/base/functionwrapper.hpp (limited to 'lib/base/functionwrapper.hpp') diff --git a/lib/base/functionwrapper.hpp b/lib/base/functionwrapper.hpp new file mode 100644 index 0000000..57cf1cb --- /dev/null +++ b/lib/base/functionwrapper.hpp @@ -0,0 +1,149 @@ +/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ + +#ifndef FUNCTIONWRAPPER_H +#define FUNCTIONWRAPPER_H + +#include "base/i2-base.hpp" +#include "base/value.hpp" +#include +#include +#include +#include +#include + +namespace icinga +{ + +template +typename std::enable_if< + std::is_class::value && + std::is_same::type, Value>::value && + boost::function_types::function_arity::value == 2, + std::function&)>>::type +WrapFunction(FuncType function) +{ + static_assert(std::is_same, 1>::type, const std::vector&>::value, "Argument type must be const std::vector"); + return function; +} + +inline std::function&)> WrapFunction(void (*function)(const std::vector&)) +{ + return [function](const std::vector& arguments) { + function(arguments); + return Empty; + }; +} + +template +std::function&)> WrapFunction(Return (*function)(const std::vector&)) +{ + return [function](const std::vector& values) -> Value { return function(values); }; +} + +template +struct indices { + using next = indices; +}; + +template +struct build_indices { + using type = typename build_indices::type::next; +}; + +template <> +struct build_indices<0> { + using type = indices<>; +}; + +template +using BuildIndices = typename build_indices::type; + +struct UnpackCaller +{ +private: + template + auto Invoke(FuncType f, const std::vector& args, indices) -> decltype(f(args[I]...)) + { + return f(args[I]...); + } + +public: + template + auto operator() (FuncType f, const std::vector& args) -> decltype(Invoke(f, args, BuildIndices{})) + { + return Invoke(f, args, BuildIndices{}); + } +}; + +template +struct FunctionWrapper +{ + static Value Invoke(FuncType function, const std::vector& arguments) + { + return UnpackCaller().operator()(function, arguments); + } +}; + +template +struct FunctionWrapper +{ + static Value Invoke(FuncType function, const std::vector& arguments) + { + UnpackCaller().operator()(function, arguments); + return Empty; + } +}; + +template +typename std::enable_if< + std::is_function::type>::value && !std::is_same&)>::value, + std::function&)>>::type +WrapFunction(FuncType function) +{ + return [function](const std::vector& arguments) { + constexpr size_t arity = boost::function_types::function_arity::type>::value; + + if (arity > 0) { + if (arguments.size() < arity) + BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function.")); + else if (arguments.size() > arity) + BOOST_THROW_EXCEPTION(std::invalid_argument("Too many arguments for function.")); + } + + using ReturnType = decltype(UnpackCaller().operator()(*static_cast(nullptr), std::vector())); + + return FunctionWrapper::Invoke(function, arguments); + }; +} + +template +typename std::enable_if< + std::is_class::value && + !(std::is_same::type, Value>::value && + boost::function_types::function_arity::value == 2), + std::function&)>>::type +WrapFunction(FuncType function) +{ + static_assert(!std::is_same, 1>::type, const std::vector&>::value, "Argument type must be const std::vector"); + + using FuncTypeInvoker = decltype(&FuncType::operator()); + + return [function](const std::vector& arguments) { + constexpr size_t arity = boost::function_types::function_arity::value - 1; + + if (arity > 0) { + if (arguments.size() < arity) + BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function.")); + else if (arguments.size() > arity) + BOOST_THROW_EXCEPTION(std::invalid_argument("Too many arguments for function.")); + } + + using ReturnType = decltype(UnpackCaller().operator()(*static_cast(nullptr), std::vector())); + + return FunctionWrapper::Invoke(function, arguments); + }; +} + +} + +#endif /* FUNCTIONWRAPPER_H */ -- cgit v1.2.3