Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: REX 2 #299

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ if(TARGET CommonLibSF)
endif()

# options if not defined
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(SFSE_SUPPORT_XBYAK "Enables trampoline support for xbyak." OFF)
option(SFSE_BUILD_TESTS "Builds the tests." OFF)

Expand Down Expand Up @@ -55,6 +58,9 @@ function(configure_target TARGET_NAME)
PUBLIC
WINVER=0x0A00 # windows 10, minimum supported version by starfield
_WIN32_WINNT=0x0A00
"$<$<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:${SFSE_SUPPORT_XBYAK}>:SFSE_SUPPORT_XBYAK=1>
WIN32_LEAN_AND_MEAN
NOMINMAX
Expand Down
278 changes: 7 additions & 271 deletions include/REX/REX.h
Original file line number Diff line number Diff line change
@@ -1,273 +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