iw5-mod/src/steam/interface.hpp

92 lines
2.0 KiB
C++
Raw Normal View History

2019-01-06 23:24:33 +01:00
#pragma once
#ifdef interface
#undef interface
#endif
namespace steam
{
2019-01-07 20:28:34 +01:00
template <size_t ...>
struct argument_size_calculator final : std::integral_constant<size_t, 0>
{
};
template <size_t X, size_t ... Xs>
struct argument_size_calculator<X, Xs...> final : std::integral_constant<
size_t, X + ((argument_size_calculator<Xs...>::value + (sizeof(void*) - 1)) & ~(sizeof(void*) - 1))>
{
};
2019-01-06 23:24:33 +01:00
class interface final
{
public:
class method final
{
public:
void* pointer = nullptr;
size_t param_size = 0;
};
class method_result final
{
public:
std::string name;
size_t param_size = 0;
2019-01-07 20:28:34 +01:00
bool name_found = false;
bool param_size_found = false;
2019-01-06 23:24:33 +01:00
};
2019-01-07 20:28:34 +01:00
interface();
2019-01-06 23:24:33 +01:00
interface(void* interface_ptr);
2019-01-07 20:28:34 +01:00
operator bool() const;
template <typename T, typename... Args>
T invoke(const std::string& method_name, Args ... args)
2019-01-06 23:24:33 +01:00
{
2019-01-07 20:28:34 +01:00
if (!this->interface_ptr_)
2019-01-06 23:24:33 +01:00
{
throw std::runtime_error("Invalid interface pointer");
}
const auto method_result = this->find_method(method_name);
2019-01-07 20:28:34 +01:00
if (!method_result.pointer)
2019-01-06 23:24:33 +01:00
{
throw std::runtime_error("Unable to find desired method");
}
2019-01-07 20:28:34 +01:00
constexpr size_t passed_argc = argument_size_calculator<sizeof(Args)...>::value;
if (passed_argc != method_result.param_size)
{
throw std::runtime_error("Invalid argument count");
}
2019-01-06 23:24:33 +01:00
2019-01-07 20:28:34 +01:00
return reinterpret_cast<T(__thiscall*)(void*, Args ...)>(method_result.pointer)(
this->interface_ptr_, args...);
2019-01-06 23:24:33 +01:00
}
2019-01-07 20:28:34 +01:00
template <typename T, typename... Args>
T invoke(const size_t table_entry, Args ... args)
2019-01-06 23:24:33 +01:00
{
if (!this->interface_ptr_)
{
throw std::runtime_error("Invalid interface pointer");
}
2019-01-07 20:28:34 +01:00
return reinterpret_cast<T(__thiscall*)(void*, Args ...)>((*this->interface_ptr_)[table_entry])(
this->interface_ptr_, args...);
2019-01-06 23:24:33 +01:00
}
private:
void*** interface_ptr_;
std::unordered_map<std::string, method> methods_;
method find_method(const std::string& name);
method search_method(const std::string& name);
method_result analyze_method(const void* method_ptr);
2019-01-07 20:28:34 +01:00
bool is_rdata(void* pointer);
2019-01-06 23:24:33 +01:00
};
}