83 lines
2.2 KiB
C++
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;
|
|
}
|
|
}; |