VoltMod
C++23 framework for CS2 server plugins
Loading...
Searching...
No Matches
BindingTypes.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <bit>
4#include <cstdint>
5#include <cstring>
6#include <utility>
7
8namespace VoltMod
9{
10
11/** Opaque address for an ABI declared only in its implementation file. */
13{
14public:
15 Address() = default;
16 explicit Address(void* address) noexcept : _address(address) {}
17
18 explicit operator bool() const noexcept { return _address != nullptr; }
19 void* Ptr() const noexcept { return _address; }
20
21private:
22 void* _address = nullptr;
23};
24
25/** Typed engine function. Calling an unbound function is undefined. */
26template <class Sig>
27class Fn;
28
29template <class Ret, class... Args>
30class Fn<Ret(Args...)>
31{
32public:
33 Fn() = default;
34 explicit Fn(void* address) noexcept : _address(address) {}
35
36 explicit operator bool() const noexcept { return _address != nullptr; }
37 void* Ptr() const noexcept { return _address; }
38
39 Ret operator()(Args... args) const
40 {
41 return std::bit_cast<Ret (*)(Args...)>(_address)(std::forward<Args>(args)...);
42 }
43
44private:
45 void* _address = nullptr;
46};
47
48/** Typed virtual function called through the object's own vtable; the first parameter is the
49 * object. Calling an unbound function is undefined. */
50template <class Sig>
52
53template <class Ret, class Object, class... Args>
54class VirtualFn<Ret(Object*, Args...)>
55{
56public:
57 VirtualFn() = default;
58 VirtualFn(int index, void* table) noexcept : _index(index), _table(table) {}
59
60 explicit operator bool() const noexcept { return _index >= 0 && _table != nullptr; }
61 int Index() const noexcept { return _index; }
62 void* Table() const noexcept { return _table; }
63
64 Ret operator()(Object* object, Args... args) const
65 {
66 auto* vtable = *reinterpret_cast<void***>(object);
67 return std::bit_cast<Ret (*)(Object*, Args...)>(vtable[_index])(object, std::forward<Args>(args)...);
68 }
69
70private:
71 int _index = -1;
72 void* _table = nullptr;
73};
74
75/** Typed byte offset. Reads and writes allow unaligned fields and do nothing while unbound. */
76template <class T>
77class Offset
78{
79public:
80 Offset() = default;
81 explicit constexpr Offset(int value) noexcept : _value(value) {}
82
83 explicit constexpr operator bool() const noexcept { return _value >= 0; }
84 constexpr int Value() const noexcept { return _value; }
85
86 T Read(const void* base) const
87 {
88 T out{};
89 if (_value >= 0 && base)
90 {
91 std::memcpy(&out, static_cast<const uint8_t*>(base) + _value, sizeof(T));
92 }
93 return out;
94 }
95
96 void Write(void* base, const T& value) const
97 {
98 if (_value >= 0 && base)
99 {
100 std::memcpy(static_cast<uint8_t*>(base) + _value, &value, sizeof(T));
101 }
102 }
103
104private:
105 int _value = -1;
106};
107
108/** Byte offset for an embedded type declared only in an implementation file. */
109template <>
111{
112public:
113 Offset() = default;
114 explicit constexpr Offset(int value) noexcept : _value(value) {}
115
116 explicit constexpr operator bool() const noexcept { return _value >= 0; }
117 constexpr int Value() const noexcept { return _value; }
118
119 const void* Ptr(const void* base) const
120 {
121 if (_value < 0 || !base)
122 {
123 return nullptr;
124 }
125 return static_cast<const uint8_t*>(base) + _value;
126 }
127
128private:
129 int _value = -1;
130};
131
132} // namespace VoltMod
Address()=default
void * Ptr() const noexcept
Address(void *address) noexcept
Ret operator()(Args... args) const
void * Ptr() const noexcept
Fn(void *address) noexcept
constexpr Offset(int value) noexcept
const void * Ptr(const void *base) const
constexpr int Value() const noexcept
constexpr int Value() const noexcept
constexpr Offset(int value) noexcept
T Read(const void *base) const
void Write(void *base, const T &value) const
Offset()=default
VirtualFn(int index, void *table) noexcept
Ret operator()(Object *object, Args... args) const
static std::string ReadFile(const std::filesystem::path &path)
Definition Loader.cpp:56