TheBrokenRail e42f46d6cc
All checks were successful
CI / Build (push) Successful in 28s
Improve Custom Wrappers
2025-04-14 13:54:55 -04:00

83 lines
2.2 KiB
C++

// Get Custom Wrapper From Object
template <typename Data>
Data **__custom_get(typename Data::__Self *self) {
return (Data **) (self + 1);
}
template <typename Data>
Data *custom_get(typename Data::__Self *self) {
return *__custom_get<Data>(self);
}
// Duplicate VTable
template <typename T>
T *custom_dup_vtable(const T *vtable) {
// Get Size
constexpr size_t rtti_size = sizeof(void *);
const unsigned char *const real_vtable = ((const unsigned char *) vtable) - rtti_size;
constexpr size_t real_vtable_size = sizeof(T) + rtti_size;
// Allocate
unsigned char *const new_vtable = (unsigned char *) ::operator new(real_vtable_size);
T *ret = (T *) (new_vtable + rtti_size);
new (ret) T;
// Copy
memcpy(new_vtable, real_vtable, real_vtable_size);
// Return
return ret;
}
// Base
template <typename A, typename B>
struct __CustomBase {
// Properties
typedef A __Self;
typedef B __VTable;
__Self *const self;
// Prevent Copying
__PREVENT_COPY(__CustomBase);
#ifdef {{ BUILDING_SYMBOLS_GUARD }}
// Constructor
__CustomBase():
self(__Self::allocate(sizeof(this)))
{
*__custom_get<__CustomBase>(self) = this;
}
#else
// Prevent Construction
__PREVENT_JUST_CONSTRUCTION(__CustomBase);
#endif
private:
// Destructor
__Self *(*__VTable::*selected_destructor)(__Self *) = &__VTable::destructor_deleting;
public:
virtual ~__CustomBase() {
(__VTable::base->*selected_destructor)(self);
}
protected:
// VTable
virtual void __patch_vtable(__VTable *vtable) {
// Patch Destructors
#define patch(type) \
vtable->type = [](__Self *self) { \
__CustomBase *obj = custom_get<__CustomBase>(self); \
obj->selected_destructor = &__VTable::type; \
delete obj; \
return self; \
}
patch(destructor_complete);
patch(destructor_deleting);
#undef patch
}
void __set_vtable() {
static __VTable *vtable = nullptr;
if (!vtable) {
// Create VTable
vtable = custom_dup_vtable(__VTable::base);
__patch_vtable(vtable);
}
this->self->vtable = vtable;
}
};