fix fields not working on macos? hopefully

This commit is contained in:
altalk23 2024-04-22 15:34:57 +03:00
parent db32732d47
commit aaf62584fb

View file

@ -66,120 +66,104 @@ namespace geode::modifier {
public:
// the constructor that constructs the fields.
// we construct the Parent first,
static void fieldConstructor(void* offsetField) requires (!HasFields<Parent>) {
std::array<std::byte, sizeof(Parent)> parentContainer;
static void fieldConstructor(void* offsetField) {
if constexpr (HasFields<Parent>) {
(void) new (offsetField) typename Parent::Fields();
}
else {
std::array<std::byte, sizeof(Parent)> parentContainer;
auto parent = new (parentContainer.data()) Parent();
auto parent = new (parentContainer.data()) Parent();
parent->Intermediate::~Intermediate();
parent->Intermediate::~Intermediate();
std::memcpy(
offsetField,
std::launder(&parentContainer[sizeof(Intermediate)]),
sizeof(Parent) - sizeof(Intermediate)
);
std::memcpy(
offsetField,
std::launder(&parentContainer[sizeof(Intermediate)]),
sizeof(Parent) - sizeof(Intermediate)
);
}
}
static void fieldDestructor(void* offsetField) requires (!HasFields<Parent>) {
std::array<std::byte, sizeof(Parent)> parentContainer;
static void fieldDestructor(void* offsetField) {
if constexpr (HasFields<Parent>) {
static_cast<typename Parent::Fields*>(offsetField)->~Fields();
}
else {
std::array<std::byte, sizeof(Parent)> parentContainer;
auto parent = new (parentContainer.data()) Intermediate();
auto parent = new (parentContainer.data()) Intermediate();
std::memcpy(
std::launder(&parentContainer[sizeof(Intermediate)]),
offsetField,
sizeof(Parent) - sizeof(Intermediate)
);
static_cast<Parent*>(parent)->Parent::~Parent();
}
operator Parent*() requires (!HasFields<Parent>) {
// get the this pointer of the base
// field intermediate is the first member of Modify
// meaning we canget the base from ourself
auto node = reinterpret_cast<Parent*>(reinterpret_cast<std::byte*>(this) - sizeof(Base));
static_assert(sizeof(Base) == offsetof(Parent, m_fields), "offsetof not correct");
// generating the container if it doesn't exist
auto container = FieldContainer::from(node, typeid(Base).name());
// the index is global across all mods, so the
// function is defined in the loader source
static size_t index = getFieldIndexForClass(typeid(Base).name());
// the fields are actually offset from their original
// offset, this is done to save on allocation and space
auto offsetField = container->getField(index);
if (!offsetField) {
offsetField = container->setField(
index, sizeof(Parent) - sizeof(Intermediate), &FieldIntermediate::fieldDestructor
std::memcpy(
std::launder(&parentContainer[sizeof(Intermediate)]),
offsetField,
sizeof(Parent) - sizeof(Intermediate)
);
FieldIntermediate::fieldConstructor(offsetField);
static_cast<Parent*>(parent)->Parent::~Parent();
}
return reinterpret_cast<Parent*>(
reinterpret_cast<std::byte*>(offsetField) - sizeof(Intermediate)
);
}
Parent* self() requires (!HasFields<Parent>) {
return this->operator Parent*();
}
auto self() {
if constexpr (HasFields<Parent>) {
// get the this pointer of the base
// field intermediate is the first member of Modify
// meaning we canget the base from ourself
auto node = reinterpret_cast<Parent*>(reinterpret_cast<std::byte*>(this) - sizeof(Base));
static_assert(sizeof(Base) == offsetof(Parent, m_fields), "offsetof not correct");
Parent* operator->() requires (!HasFields<Parent>) {
// workaround for "static assertion is not an integral constant expression" in CLion
// while the solution in https://github.com/microsoft/STL/issues/3311 works, you can't provide
// cli args to clang-tidy in clion, so we use this workaround instead
// https://youtrack.jetbrains.com/issue/CPP-27446/spurious-offsetof-in-staticassert-error-from-clangd#focus=Comments-27-8172811.0-0
// update: that workaround didn't work,
// undefining and re-defining offsetof caused another error further down
// so we're doing this now
#ifdef __CLION_IDE__
return reinterpret_cast<Parent*>(69420);
#else
return this->operator Parent*();
#endif
}
// generating the container if it doesn't exist
auto container = FieldContainer::from(node, typeid(Base).name());
static void fieldConstructor(void* offsetField) requires (HasFields<Parent>) {
(void) new (offsetField) typename Parent::Fields();
}
// the index is global across all mods, so the
// function is defined in the loader source
static size_t index = getFieldIndexForClass(typeid(Base).name());
static void fieldDestructor(void* offsetField) requires (HasFields<Parent>) {
static_cast<typename Parent::Fields*>(offsetField)->~Fields();
}
// the fields are actually offset from their original
// offset, this is done to save on allocation and space
auto offsetField = container->getField(index);
if (!offsetField) {
offsetField = container->setField(
index, sizeof(typename Parent::Fields), &FieldIntermediate::fieldDestructor
);
auto self() requires (HasFields<Parent>) {
// get the this pointer of the base
// field intermediate is the first member of Modify
// meaning we canget the base from ourself
auto node = reinterpret_cast<Parent*>(reinterpret_cast<std::byte*>(this) - sizeof(Base));
static_assert(sizeof(Base) == offsetof(Parent, m_fields), "offsetof not correct");
FieldIntermediate::fieldConstructor(offsetField);
}
// generating the container if it doesn't exist
auto container = FieldContainer::from(node, typeid(Base).name());
return reinterpret_cast<typename Parent::Fields*>(offsetField);
}
else {
// get the this pointer of the base
// field intermediate is the first member of Modify
// meaning we canget the base from ourself
auto node = reinterpret_cast<Parent*>(reinterpret_cast<std::byte*>(this) - sizeof(Base));
static_assert(sizeof(Base) == offsetof(Parent, m_fields), "offsetof not correct");
// the index is global across all mods, so the
// function is defined in the loader source
static size_t index = getFieldIndexForClass(typeid(Base).name());
// generating the container if it doesn't exist
auto container = FieldContainer::from(node, typeid(Base).name());
// the fields are actually offset from their original
// offset, this is done to save on allocation and space
auto offsetField = container->getField(index);
if (!offsetField) {
offsetField = container->setField(
index, sizeof(typename Parent::Fields), &FieldIntermediate::fieldDestructor
// the index is global across all mods, so the
// function is defined in the loader source
static size_t index = getFieldIndexForClass(typeid(Base).name());
// the fields are actually offset from their original
// offset, this is done to save on allocation and space
auto offsetField = container->getField(index);
if (!offsetField) {
offsetField = container->setField(
index, sizeof(Parent) - sizeof(Intermediate), &FieldIntermediate::fieldDestructor
);
FieldIntermediate::fieldConstructor(offsetField);
}
return reinterpret_cast<Parent*>(
reinterpret_cast<std::byte*>(offsetField) - sizeof(Intermediate)
);
FieldIntermediate::fieldConstructor(offsetField);
}
return reinterpret_cast<typename Parent::Fields*>(offsetField);
}
auto operator->() requires (HasFields<Parent>) {
auto operator->() {
// workaround for "static assertion is not an integral constant expression" in CLion
// while the solution in https://github.com/microsoft/STL/issues/3311 works, you can't provide
// cli args to clang-tidy in clion, so we use this workaround instead