Skip to content

Commit

Permalink
Merge pull request #150 from shad0wshayd3-TES5/dev-rex
Browse files Browse the repository at this point in the history
feat: REX 2
  • Loading branch information
powerof3 authored Nov 16, 2024
2 parents 1b38981 + 92c1ee1 commit 105df57
Show file tree
Hide file tree
Showing 13 changed files with 1,100 additions and 272 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
cmake_minimum_required(VERSION 3.19)

option(REX_OPTION_INI "Enables ini config support for REX." OFF)
option(REX_OPTION_JSON "Enables json config support for REX." OFF)
option(REX_OPTION_TOML "Enables toml config support for REX." OFF)
option(SKSE_SUPPORT_XBYAK "Enables trampoline support for Xbyak." OFF)
option(SKYRIM_SUPPORT_AE "Enables support for Skyrim AE" OFF)

Expand Down Expand Up @@ -39,6 +42,9 @@ target_compile_definitions(
PUBLIC
WINVER=0x0601 # windows 7, minimum supported version by skyrim special edition
_WIN32_WINNT=0x0601
"$<$<BOOL:${REX_OPTION_INI}>:REX_OPTION_INI=1>"
"$<$<BOOL:${REX_OPTION_JSON}>:REX_OPTION_JSON=1>"
"$<$<BOOL:${REX_OPTION_TOML}>:REX_OPTION_TOML=1>"
"$<$<BOOL:${SKSE_SUPPORT_XBYAK}>:SKSE_SUPPORT_XBYAK=1>"
"$<$<BOOL:${SKYRIM_SUPPORT_AE}>:SKYRIM_SUPPORT_AE=1>"
)
Expand Down
8 changes: 8 additions & 0 deletions cmake/sourcelist.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -1671,6 +1671,13 @@ set(SOURCES
include/REX/PS4.h
include/REX/PS4/SCEPAD.h
include/REX/REX.h
include/REX/REX/Enum.h
include/REX/REX/EnumSet.h
include/REX/REX/INI.h
include/REX/REX/JSON.h
include/REX/REX/Setting.h
include/REX/REX/Singleton.h
include/REX/REX/TOML.h
include/REX/W32.h
include/REX/W32/ADVAPI32.h
include/REX/W32/BASE.h
Expand Down Expand Up @@ -2046,6 +2053,7 @@ set(SOURCES
src/REL/Module.cpp
src/REL/Relocation.cpp
src/REL/Version.cpp
src/REX/REX.cpp
src/REX/W32.cpp
src/SKSE/API.cpp
src/SKSE/IAT.cpp
Expand Down
277 changes: 7 additions & 270 deletions include/REX/REX.h
Original file line number Diff line number Diff line change
@@ -1,272 +1,9 @@
#pragma once

namespace REX
{
template <
class E,
class U = std::underlying_type_t<E>>
class Enum
{
public:
using enum_type = E;
using underlying_type = U;

static_assert(std::is_enum_v<E>, "Enum<E, ...> must be an enum");
static_assert(std::is_integral_v<U>, "Enum<..., U> must be an integral");

constexpr Enum() noexcept = default;
constexpr Enum(const Enum&) noexcept = default;
constexpr Enum(Enum&&) noexcept = default;

template <class U2> // NOLINTNEXTLINE(google-explicit-constructor)
constexpr Enum(Enum<E, U2> a_rhs) noexcept :
_impl(static_cast<U>(a_rhs.get()))
{}

constexpr Enum(E a_value) noexcept :
_impl(static_cast<U>(a_value))
{}

~Enum() noexcept = default;

constexpr Enum& operator=(const Enum&) noexcept = default;
constexpr Enum& operator=(Enum&&) noexcept = default;

template <class U2>
constexpr Enum& operator=(Enum<E, U2> a_rhs) noexcept
{
_impl = static_cast<U>(a_rhs.get());
}

constexpr Enum& operator=(E a_value) noexcept
{
_impl = static_cast<U>(a_value);
return *this;
}

public:
[[nodiscard]] explicit constexpr operator bool() const noexcept { return _impl != static_cast<U>(0); }

[[nodiscard]] constexpr E operator*() const noexcept { return get(); }
[[nodiscard]] constexpr E get() const noexcept { return static_cast<E>(_impl); }
[[nodiscard]] constexpr U underlying() const noexcept { return _impl; }

public:
friend constexpr bool operator==(Enum a_lhs, Enum a_rhs) noexcept { return a_lhs.underlying() == a_rhs.underlying(); }
friend constexpr bool operator==(Enum a_lhs, E a_rhs) noexcept { return a_lhs.underlying() == static_cast<U>(a_rhs); }
friend constexpr bool operator==(E a_lhs, Enum a_rhs) noexcept { return static_cast<U>(a_lhs) == a_rhs.underlying(); }

private:
U _impl{ 0 };
};

template <class... Args>
Enum(Args...) -> Enum<
std::common_type_t<Args...>,
std::underlying_type_t<
std::common_type_t<Args...>>>;
}

namespace REX
{
template <
class E,
class U = std::underlying_type_t<E>>
class EnumSet
{
public:
using enum_type = E;
using underlying_type = U;

static_assert(std::is_enum_v<E>, "EnumSet<E, ...> must be an enum");
static_assert(std::is_integral_v<U>, "EnumSet<..., U> must be an integral");

constexpr EnumSet() noexcept = default;
constexpr EnumSet(const EnumSet&) noexcept = default;
constexpr EnumSet(EnumSet&&) noexcept = default;

template <class U2> // NOLINTNEXTLINE(google-explicit-constructor)
constexpr EnumSet(EnumSet<E, U2> a_rhs) noexcept :
_impl(static_cast<U>(a_rhs.get()))
{}

template <class... Args>
constexpr EnumSet(Args... a_values) noexcept
requires(std::same_as<Args, E>&&...) :
_impl((static_cast<U>(a_values) | ...))
{}

~EnumSet() noexcept = default;

constexpr EnumSet& operator=(const EnumSet&) noexcept = default;
constexpr EnumSet& operator=(EnumSet&&) noexcept = default;

template <class U2>
constexpr EnumSet& operator=(EnumSet<E, U2> a_rhs) noexcept
{
_impl = static_cast<U>(a_rhs.get());
}

constexpr EnumSet& operator=(E a_value) noexcept
{
_impl = static_cast<U>(a_value);
return *this;
}

public:
[[nodiscard]] explicit constexpr operator bool() const noexcept { return _impl != static_cast<U>(0); }

[[nodiscard]] constexpr E operator*() const noexcept { return get(); }
[[nodiscard]] constexpr E get() const noexcept { return static_cast<E>(_impl); }
[[nodiscard]] constexpr U underlying() const noexcept { return _impl; }

public:
template <class... Args>
constexpr EnumSet& set(Args... a_args) noexcept
requires(std::same_as<Args, E>&&...)
{
_impl |= (static_cast<U>(a_args) | ...);
return *this;
}

template <class... Args>
constexpr EnumSet& set(bool a_set, Args... a_args) noexcept
requires(std::same_as<Args, E>&&...)
{
if (a_set)
_impl |= (static_cast<U>(a_args) | ...);
else
_impl &= ~(static_cast<U>(a_args) | ...);

return *this;
}

template <class... Args>
constexpr EnumSet& reset(Args... a_args) noexcept
requires(std::same_as<Args, E>&&...)
{
_impl &= ~(static_cast<U>(a_args) | ...);
return *this;
}

constexpr EnumSet& reset() noexcept
{
_impl = 0;
return *this;
}

template <class... Args>
[[nodiscard]] constexpr bool any(Args... a_args) const noexcept
requires(std::same_as<Args, E>&&...)
{
return (_impl & (static_cast<U>(a_args) | ...)) != static_cast<U>(0);
}

template <class... Args>
[[nodiscard]] constexpr bool all(Args... a_args) const noexcept
requires(std::same_as<Args, E>&&...)
{
return (_impl & (static_cast<U>(a_args) | ...)) == (static_cast<U>(a_args) | ...);
}

template <class... Args>
[[nodiscard]] constexpr bool none(Args... a_args) const noexcept
requires(std::same_as<Args, E>&&...)
{
return (_impl & (static_cast<U>(a_args) | ...)) == static_cast<U>(0);
}

public:
friend constexpr bool operator==(EnumSet a_lhs, EnumSet a_rhs) noexcept { return a_lhs.underlying() == a_rhs.underlying(); }
friend constexpr bool operator==(EnumSet a_lhs, E a_rhs) noexcept { return a_lhs.underlying() == static_cast<U>(a_rhs); }
friend constexpr bool operator==(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<U>(a_lhs) == a_rhs.underlying(); }

friend constexpr std::strong_ordering operator<=>(EnumSet a_lhs, EnumSet a_rhs) noexcept { return a_lhs.underlying() <=> a_rhs.underlying(); }
friend constexpr std::strong_ordering operator<=>(EnumSet a_lhs, E a_rhs) noexcept { return a_lhs.underlying() <=> static_cast<U>(a_rhs); }
friend constexpr std::strong_ordering operator<=>(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<U>(a_lhs) <=> a_rhs.underlying(); }

friend constexpr EnumSet operator&(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() & a_rhs.underlying()); }
friend constexpr EnumSet operator&(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() & static_cast<U>(a_rhs)); }
friend constexpr EnumSet operator&(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) & a_rhs.underlying()); }

friend constexpr EnumSet& operator&=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs & a_rhs; }
friend constexpr EnumSet& operator&=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs & a_rhs; }

friend constexpr EnumSet operator|(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() | a_rhs.underlying()); }
friend constexpr EnumSet operator|(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() | static_cast<U>(a_rhs)); }
friend constexpr EnumSet operator|(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) | a_rhs.underlying()); }

friend constexpr EnumSet& operator|=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs | a_rhs; }
friend constexpr EnumSet& operator|=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs | a_rhs; }

friend constexpr EnumSet operator^(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() ^ a_rhs.underlying()); }
friend constexpr EnumSet operator^(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() ^ static_cast<U>(a_rhs)); }
friend constexpr EnumSet operator^(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) ^ a_rhs.underlying()); }

friend constexpr EnumSet& operator^=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs ^ a_rhs; }
friend constexpr EnumSet& operator^=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs ^ a_rhs; }

friend constexpr EnumSet operator+(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() + a_rhs.underlying()); }
friend constexpr EnumSet operator+(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() + static_cast<U>(a_rhs)); }
friend constexpr EnumSet operator+(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) + a_rhs.underlying()); }

friend constexpr EnumSet& operator+=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs + a_rhs; }
friend constexpr EnumSet& operator+=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs + a_rhs; }

friend constexpr EnumSet operator-(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() - a_rhs.underlying()); }
friend constexpr EnumSet operator-(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() - static_cast<U>(a_rhs)); }
friend constexpr EnumSet operator-(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) - a_rhs.underlying()); }

friend constexpr EnumSet& operator-=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs - a_rhs; }
friend constexpr EnumSet& operator-=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs - a_rhs; }

friend constexpr EnumSet operator<<(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() << a_rhs.underlying()); }
friend constexpr EnumSet operator<<(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() << static_cast<U>(a_rhs)); }
friend constexpr EnumSet operator<<(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) << a_rhs.underlying()); }

friend constexpr EnumSet& operator<<=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs << a_rhs; }
friend constexpr EnumSet& operator<<=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs << a_rhs; }

friend constexpr EnumSet operator>>(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() >> a_rhs.underlying()); }
friend constexpr EnumSet operator>>(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() >> static_cast<U>(a_rhs)); }
friend constexpr EnumSet operator>>(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) >> a_rhs.underlying()); }

friend constexpr EnumSet& operator>>=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs >> a_rhs; }
friend constexpr EnumSet& operator>>=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs >> a_rhs; }

friend constexpr EnumSet& operator~(EnumSet& a_lhs) noexcept { return a_lhs = ~a_lhs.underlying(); }

private:
U _impl{ 0 };
};

template <class... Args>
EnumSet(Args...) -> EnumSet<
std::common_type_t<Args...>,
std::underlying_type_t<
std::common_type_t<Args...>>>;
}

namespace REX
{
template <class T>
class Singleton
{
public:
static T* GetSingleton()
{
static T singleton;
return std::addressof(singleton);
}

protected:
Singleton() = default;
~Singleton() = default;

Singleton(const Singleton&) = delete;
Singleton(Singleton&&) = delete;

Singleton& operator=(const Singleton&) = delete;
Singleton& operator=(Singleton&&) = delete;
};
}
#include "REX/REX/Enum.h"
#include "REX/REX/EnumSet.h"
#include "REX/REX/INI.h"
#include "REX/REX/JSON.h"
#include "REX/REX/Setting.h"
#include "REX/REX/Singleton.h"
#include "REX/REX/TOML.h"
68 changes: 68 additions & 0 deletions include/REX/REX/Enum.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#pragma once

namespace REX
{
template <
class E,
class U = std::underlying_type_t<E>>
class Enum
{
public:
using enum_type = E;
using underlying_type = U;

static_assert(std::is_enum_v<E>, "Enum<E, ...> must be an enum");
static_assert(std::is_integral_v<U>, "Enum<..., U> must be an integral");

constexpr Enum() noexcept = default;
constexpr Enum(const Enum&) noexcept = default;
constexpr Enum(Enum&&) noexcept = default;

template <class U2> // NOLINTNEXTLINE(google-explicit-constructor)
constexpr Enum(Enum<E, U2> a_rhs) noexcept :
_impl(static_cast<U>(a_rhs.get()))
{}

constexpr Enum(E a_value) noexcept :
_impl(static_cast<U>(a_value))
{}

~Enum() noexcept = default;

constexpr Enum& operator=(const Enum&) noexcept = default;
constexpr Enum& operator=(Enum&&) noexcept = default;

template <class U2>
constexpr Enum& operator=(Enum<E, U2> a_rhs) noexcept
{
_impl = static_cast<U>(a_rhs.get());
}

constexpr Enum& operator=(E a_value) noexcept
{
_impl = static_cast<U>(a_value);
return *this;
}

public:
[[nodiscard]] explicit constexpr operator bool() const noexcept { return _impl != static_cast<U>(0); }

[[nodiscard]] constexpr E operator*() const noexcept { return get(); }
[[nodiscard]] constexpr E get() const noexcept { return static_cast<E>(_impl); }
[[nodiscard]] constexpr U underlying() const noexcept { return _impl; }

public:
friend constexpr bool operator==(Enum a_lhs, Enum a_rhs) noexcept { return a_lhs.underlying() == a_rhs.underlying(); }
friend constexpr bool operator==(Enum a_lhs, E a_rhs) noexcept { return a_lhs.underlying() == static_cast<U>(a_rhs); }
friend constexpr bool operator==(E a_lhs, Enum a_rhs) noexcept { return static_cast<U>(a_lhs) == a_rhs.underlying(); }

private:
U _impl{ 0 };
};

template <class... Args>
Enum(Args...) -> Enum<
std::common_type_t<Args...>,
std::underlying_type_t<
std::common_type_t<Args...>>>;
}
Loading

0 comments on commit 105df57

Please sign in to comment.