Skip to content

Commit

Permalink
refactor(hook): allow to pass lambda instead of std::function
Browse files Browse the repository at this point in the history
  • Loading branch information
Curve committed Dec 26, 2023
1 parent 22e7bfa commit 5147dd1
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 32 deletions.
24 changes: 16 additions & 8 deletions include/lime/hooks/hook.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,19 @@ namespace lime
template <typename T>
concept Address = requires() { requires std::integral<T> || std::is_pointer_v<T>; };

template <typename Hook, typename Signature>
consteval auto lambda_target();
template <typename T>
concept PointerDecay = requires(T callable) {
{ +callable };
};

template <typename Hook, typename Signature>
using lambda_target_t = typename decltype(lambda_target<Hook, Signature>())::type;
template <typename T, typename Signature>
consteval auto can_invoke();

template <typename T, typename Signature>
concept Lambda = requires(T callable) {
requires not(Address<T> or PointerDecay<T>);
requires can_invoke<T, Signature>();
};

template <typename Signature>
class hook : public hook_base
Expand All @@ -61,12 +69,12 @@ namespace lime
signature_t original() const;

public:
template <Address Source, Address Target>
[[nodiscard]] static rtn_t<std::unique_ptr> create(Source source, Target target);
[[nodiscard]] static rtn_t<std::unique_ptr> create(Address auto source, Address auto target);

public:
template <Address Source>
static rtn_t<std::add_pointer_t> create(Source source, lambda_target_t<hook *, Signature> &&target);
template <typename Callable>
requires Lambda<Callable, Signature>
static rtn_t<std::add_pointer_t> create(Address auto source, Callable &&target);
};
} // namespace lime

Expand Down
41 changes: 17 additions & 24 deletions include/lime/hooks/hook.inl
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,19 @@
#include "hook.hpp"

#include <cassert>
#include <functional>

#include <boost/callable_traits.hpp>

namespace lime
{
template <typename Hook, typename Signature>
consteval auto lambda_target()
template <typename Lambda, typename Signature>
consteval auto can_invoke()
{
using args_t = boost::callable_traits::args_t<Signature>;
using return_t = boost::callable_traits::return_type_t<Signature>;
using args_t = boost::callable_traits::args_t<Signature>;
using rtn_t = boost::callable_traits::return_type_t<Signature>;

return std::apply(
[]<typename... T>(T &&...)
{
using function_t = std::function<return_t(Hook, T...)>;
return std::type_identity<function_t>{};
},
args_t{});
return std::apply([]<typename... T>(T &&...)
{ return std::is_same_v<std::invoke_result_t<Lambda, hook<Signature> *, T...>, rtn_t>; },
args_t{});
}

template <typename Signature>
Expand All @@ -30,8 +24,7 @@ namespace lime
}

template <typename Signature>
template <Address Source, Address Target>
hook<Signature>::template rtn_t<std::unique_ptr> hook<Signature>::create(Source source, Target target)
hook<Signature>::rtn_t<std::unique_ptr> hook<Signature>::create(Address auto source, Address auto target)
{
auto source_address = reinterpret_cast<std::uintptr_t>(source);
auto target_address = reinterpret_cast<std::uintptr_t>(target);
Expand All @@ -48,35 +41,35 @@ namespace lime
}

template <typename Signature>
template <Address Source>
hook<Signature>::template rtn_t<std::add_pointer_t>
hook<Signature>::create(Source source, lambda_target_t<hook *, Signature> &&target)
template <typename Callable>
requires Lambda<Callable, Signature>
hook<Signature>::rtn_t<std::add_pointer_t> hook<Signature>::create(Address auto source, Callable &&target)
{
using args_t = boost::callable_traits::args_t<Signature>;
using rtn_t = boost::callable_traits::return_type_t<Signature>;

static hook<Signature> *hook;
static auto lambda = std::move(target);
static hook<Signature> *rtn;
static auto lambda = std::forward<Callable>(target);

static constexpr auto wrapper = std::apply(
[]<typename... T>(T &&...)
{
return [](T... args) -> rtn_t
{
return lambda(hook, std::forward<T>(args)...);
return lambda(rtn, std::forward<T>(args)...);
};
},
args_t{});

auto result = create(source, static_cast<signature_t>(wrapper));
auto result = create(source, +wrapper);

if (!result)
{
return tl::make_unexpected(result.error());
}

hook = result->release();
rtn = result->release();

return hook;
return rtn;
}
} // namespace lime

0 comments on commit 5147dd1

Please sign in to comment.