diff --git a/LiteLoader/third-party/include/ModUtils/ModUtils.h b/LiteLoader/third-party/include/ModUtils/ModUtils.h index 07e710e..968710d 100644 --- a/LiteLoader/third-party/include/ModUtils/ModUtils.h +++ b/LiteLoader/third-party/include/ModUtils/ModUtils.h @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/LiteLoader/third-party/include/SQLiteCpp/Backup.h b/LiteLoader/third-party/include/SQLiteCpp/Backup.h index 61e21d0..bfc3b1c 100644 --- a/LiteLoader/third-party/include/SQLiteCpp/Backup.h +++ b/LiteLoader/third-party/include/SQLiteCpp/Backup.h @@ -11,7 +11,7 @@ */ #pragma once -#include "Database.h" +#include #include diff --git a/LiteLoader/third-party/include/SQLiteCpp/Column.h b/LiteLoader/third-party/include/SQLiteCpp/Column.h index 06adba9..88a7fb3 100644 --- a/LiteLoader/third-party/include/SQLiteCpp/Column.h +++ b/LiteLoader/third-party/include/SQLiteCpp/Column.h @@ -10,8 +10,8 @@ */ #pragma once -#include "Statement.h" -#include "Exception.h" +#include +#include #include #include // For INT_MAX diff --git a/LiteLoader/third-party/include/SQLiteCpp/Database.h b/LiteLoader/third-party/include/SQLiteCpp/Database.h index c39a6a1..c471e9b 100644 --- a/LiteLoader/third-party/include/SQLiteCpp/Database.h +++ b/LiteLoader/third-party/include/SQLiteCpp/Database.h @@ -10,8 +10,8 @@ */ #pragma once -#include "Column.h" -#include "Utils.h" // definition of nullptr for C++98/C++03 compilers +#include +#include // definition of nullptr for C++98/C++03 compilers #include diff --git a/LiteLoader/third-party/include/SQLiteCpp/SQLiteCpp.h b/LiteLoader/third-party/include/SQLiteCpp/SQLiteCpp.h index cfabd8c..a189840 100644 --- a/LiteLoader/third-party/include/SQLiteCpp/SQLiteCpp.h +++ b/LiteLoader/third-party/include/SQLiteCpp/SQLiteCpp.h @@ -18,12 +18,12 @@ // Include useful headers of SQLiteC++ -#include "Assertion.h" -#include "Exception.h" -#include "Database.h" -#include "Statement.h" -#include "Column.h" -#include "Transaction.h" +#include +#include +#include +#include +#include +#include /** diff --git a/LiteLoader/third-party/include/SQLiteCpp/Statement.h b/LiteLoader/third-party/include/SQLiteCpp/Statement.h index 0a3f4ca..ecf417b 100644 --- a/LiteLoader/third-party/include/SQLiteCpp/Statement.h +++ b/LiteLoader/third-party/include/SQLiteCpp/Statement.h @@ -10,7 +10,7 @@ */ #pragma once -#include "Exception.h" +#include #include #include diff --git a/LiteLoader/third-party/include/SQLiteCpp/Transaction.h b/LiteLoader/third-party/include/SQLiteCpp/Transaction.h index c8f3455..0fbf9cf 100644 --- a/LiteLoader/third-party/include/SQLiteCpp/Transaction.h +++ b/LiteLoader/third-party/include/SQLiteCpp/Transaction.h @@ -10,7 +10,7 @@ */ #pragma once -#include "Exception.h" +#include namespace SQLite diff --git a/LiteLoader/third-party/include/SQLiteCpp/VariadicBind.h b/LiteLoader/third-party/include/SQLiteCpp/VariadicBind.h index fa10416..24e5e5f 100644 --- a/LiteLoader/third-party/include/SQLiteCpp/VariadicBind.h +++ b/LiteLoader/third-party/include/SQLiteCpp/VariadicBind.h @@ -13,7 +13,7 @@ #if (__cplusplus >= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) ) // c++14: Visual Studio 2015 -#include "Statement.h" +#include /// @cond #include diff --git a/LiteLoader/third-party/include/compact_enc_det/compact_enc_det.h b/LiteLoader/third-party/include/compact_enc_det/compact_enc_det.h index 2b37ef7..01adf45 100644 --- a/LiteLoader/third-party/include/compact_enc_det/compact_enc_det.h +++ b/LiteLoader/third-party/include/compact_enc_det/compact_enc_det.h @@ -17,8 +17,8 @@ #ifndef COMPACT_ENC_DET_COMPACT_ENC_DET_H_ #define COMPACT_ENC_DET_COMPACT_ENC_DET_H_ -#include "third-party/include/compact_enc_det/util/encodings/encodings.h" // for Encoding -#include "third-party/include/compact_enc_det/util/languages/languages.h" // for Language +#include "util/encodings/encodings.h" // for Encoding +#include "util/languages/languages.h" // for Language #include diff --git a/LiteLoader/third-party/include/compact_enc_det/compact_enc_det_generated_tables2.h b/LiteLoader/third-party/include/compact_enc_det/compact_enc_det_generated_tables2.h index ac04e5e..4ecf966 100644 --- a/LiteLoader/third-party/include/compact_enc_det/compact_enc_det_generated_tables2.h +++ b/LiteLoader/third-party/include/compact_enc_det/compact_enc_det_generated_tables2.h @@ -14,7 +14,7 @@ // //////////////////////////////////////////////////////////////////////////////// -#include "third-party/include/compact_enc_det/util/basictypes.h" +#include "util/basictypes.h" static const uint8 ced_hires_0[1024] = { 128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, diff --git a/LiteLoader/third-party/include/compact_enc_det/compact_enc_det_hint_code.h b/LiteLoader/third-party/include/compact_enc_det/compact_enc_det_hint_code.h index 2521292..53fe67a 100644 --- a/LiteLoader/third-party/include/compact_enc_det/compact_enc_det_hint_code.h +++ b/LiteLoader/third-party/include/compact_enc_det/compact_enc_det_hint_code.h @@ -19,8 +19,8 @@ #include // for string -#include "third-party/include/compact_enc_det/util/basictypes.h" // for uint32 -#include "third-party/include/compact_enc_det/util/encodings/encodings.h" // for Encoding +#include "util/basictypes.h" // for uint32 +#include "util/encodings/encodings.h" // for Encoding using std::string; diff --git a/LiteLoader/third-party/include/entt/config/config.h b/LiteLoader/third-party/include/entt/config/config.h index c2276c5..06c42e8 100644 --- a/LiteLoader/third-party/include/entt/config/config.h +++ b/LiteLoader/third-party/include/entt/config/config.h @@ -1,85 +1,81 @@ #ifndef ENTT_CONFIG_CONFIG_H #define ENTT_CONFIG_CONFIG_H +#include "version.h" #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION) -# define ENTT_NOEXCEPT noexcept -# define ENTT_THROW throw -# define ENTT_TRY try -# define ENTT_CATCH catch(...) +# define ENTT_CONSTEXPR +# define ENTT_THROW throw +# define ENTT_TRY try +# define ENTT_CATCH catch(...) #else -# define ENTT_NOEXCEPT -# define ENTT_THROW -# define ENTT_TRY if(true) -# define ENTT_CATCH if(false) +# define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20) +# define ENTT_THROW +# define ENTT_TRY if(true) +# define ENTT_CATCH if(false) #endif - -#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L -# include -# define ENTT_LAUNDER(expr) std::launder(expr) +#ifdef ENTT_USE_ATOMIC +# include +# define ENTT_MAYBE_ATOMIC(Type) std::atomic #else -# define ENTT_LAUNDER(expr) expr +# define ENTT_MAYBE_ATOMIC(Type) Type #endif - -#ifndef ENTT_USE_ATOMIC -# define ENTT_MAYBE_ATOMIC(Type) Type -#else -# include -# define ENTT_MAYBE_ATOMIC(Type) std::atomic -#endif - - #ifndef ENTT_ID_TYPE -# include -# define ENTT_ID_TYPE std::uint32_t +# include +# define ENTT_ID_TYPE std::uint32_t #endif - -#ifdef ENTT_SPARSE_PAGE - static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two"); -#else -# define ENTT_SPARSE_PAGE 4096 +#ifndef ENTT_SPARSE_PAGE +# define ENTT_SPARSE_PAGE 4096 #endif - -#ifdef ENTT_PACKED_PAGE -static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two"); -#else -# define ENTT_PACKED_PAGE 1024 +#ifndef ENTT_PACKED_PAGE +# define ENTT_PACKED_PAGE 1024 #endif - #ifdef ENTT_DISABLE_ASSERT -# undef ENTT_ASSERT -# define ENTT_ASSERT(...) (void(0)) +# undef ENTT_ASSERT +# define ENTT_ASSERT(condition, msg) (void(0)) #elif !defined ENTT_ASSERT -# include -# define ENTT_ASSERT(condition, ...) assert(condition) +# include +# define ENTT_ASSERT(condition, msg) assert(condition) #endif +#ifdef ENTT_DISABLE_ASSERT +# undef ENTT_ASSERT_CONSTEXPR +# define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0)) +#elif !defined ENTT_ASSERT_CONSTEXPR +# define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg) +#endif #ifdef ENTT_NO_ETO -# include -# define ENTT_IGNORE_IF_EMPTY std::false_type +# define ENTT_ETO_TYPE(Type) void #else -# include -# define ENTT_IGNORE_IF_EMPTY std::true_type +# define ENTT_ETO_TYPE(Type) Type #endif - -#ifndef ENTT_STANDARD_CPP +#ifdef ENTT_STANDARD_CPP +# define ENTT_NONSTD false +#else +# define ENTT_NONSTD true # if defined __clang__ || defined __GNUC__ -# define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__ -# define ENTT_PRETTY_FUNCTION_PREFIX '=' -# define ENTT_PRETTY_FUNCTION_SUFFIX ']' +# define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__ +# define ENTT_PRETTY_FUNCTION_PREFIX '=' +# define ENTT_PRETTY_FUNCTION_SUFFIX ']' # elif defined _MSC_VER -# define ENTT_PRETTY_FUNCTION __FUNCSIG__ -# define ENTT_PRETTY_FUNCTION_PREFIX '<' -# define ENTT_PRETTY_FUNCTION_SUFFIX '>' -# endif +# define ENTT_PRETTY_FUNCTION __FUNCSIG__ +# define ENTT_PRETTY_FUNCTION_PREFIX '<' +# define ENTT_PRETTY_FUNCTION_SUFFIX '>' +# endif #endif +#if defined _MSC_VER +# pragma detect_mismatch("entt.version", ENTT_VERSION) +# pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY)) +# pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE)) +# pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD)) +#endif #endif diff --git a/LiteLoader/third-party/include/entt/config/version.h b/LiteLoader/third-party/include/entt/config/version.h index e7b9571..a07438d 100644 --- a/LiteLoader/third-party/include/entt/config/version.h +++ b/LiteLoader/third-party/include/entt/config/version.h @@ -1,10 +1,14 @@ #ifndef ENTT_CONFIG_VERSION_H #define ENTT_CONFIG_VERSION_H +#include "macro.h" #define ENTT_VERSION_MAJOR 3 -#define ENTT_VERSION_MINOR 8 -#define ENTT_VERSION_PATCH 1 +#define ENTT_VERSION_MINOR 11 +#define ENTT_VERSION_PATCH 0 +#define ENTT_VERSION \ + ENTT_XSTR(ENTT_VERSION_MAJOR) \ + "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH) #endif diff --git a/LiteLoader/third-party/include/entt/core/algorithm.hpp b/LiteLoader/third-party/include/entt/core/algorithm.hpp index eda7e8d..44c47ef 100644 --- a/LiteLoader/third-party/include/entt/core/algorithm.hpp +++ b/LiteLoader/third-party/include/entt/core/algorithm.hpp @@ -1,18 +1,15 @@ #ifndef ENTT_CORE_ALGORITHM_HPP #define ENTT_CORE_ALGORITHM_HPP - -#include -#include -#include #include #include +#include +#include +#include #include "utility.hpp" - namespace entt { - /** * @brief Function object to wrap `std::sort` in a class type. * @@ -36,12 +33,11 @@ struct std_sort { * @param args Arguments to forward to the sort function, if any. */ template, typename... Args> - void operator()(It first, It last, Compare compare = Compare{}, Args &&... args) const { + void operator()(It first, It last, Compare compare = Compare{}, Args &&...args) const { std::sort(std::forward(args)..., std::move(first), std::move(last), std::move(compare)); } }; - /*! @brief Function object for performing insertion sort. */ struct insertion_sort { /** @@ -62,8 +58,8 @@ struct insertion_sort { auto value = std::move(*it); auto pre = it; - for(; pre > first && compare(value, *(pre-1)); --pre) { - *pre = std::move(*(pre-1)); + for(; pre > first && compare(value, *(pre - 1)); --pre) { + *pre = std::move(*(pre - 1)); } *pre = std::move(value); @@ -72,7 +68,6 @@ struct insertion_sort { } }; - /** * @brief Function object for performing LSD radix sort. * @tparam Bit Number of bits processed per pass. @@ -137,8 +132,6 @@ struct radix_sort { } }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/core/any.hpp b/LiteLoader/third-party/include/entt/core/any.hpp index 39248f3..0095a40 100644 --- a/LiteLoader/third-party/include/entt/core/any.hpp +++ b/LiteLoader/third-party/include/entt/core/any.hpp @@ -1,21 +1,47 @@ #ifndef ENTT_CORE_ANY_HPP #define ENTT_CORE_ANY_HPP - #include -#include #include #include #include -#include "third-party/include/entt/config/config.h" -#include "utility.hpp" +#include "../config/config.h" +#include "../core/utility.hpp" #include "fwd.hpp" #include "type_info.hpp" #include "type_traits.hpp" - namespace entt { +/** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + +namespace internal { + +enum class any_operation : std::uint8_t { + copy, + move, + transfer, + assign, + destroy, + compare, + get +}; + +enum class any_policy : std::uint8_t { + owner, + ref, + cref +}; + +} // namespace internal + +/** + * Internal details not to be documented. + * @endcond + */ /** * @brief A SBO friendly, type-safe container for single values of any type. @@ -24,116 +50,108 @@ namespace entt { */ template class basic_any { - enum class operation: std::uint8_t { COPY, MOVE, DTOR, COMP, ADDR, CADDR, TYPE }; - enum class policy: std::uint8_t { OWNER, REF, CREF }; + using operation = internal::any_operation; + using policy = internal::any_policy; + using vtable_type = const void *(const operation, const basic_any &, const void *); - using storage_type = std::aligned_storage_t; - using vtable_type = const void *(const operation, const basic_any &, void *); + struct storage_type { + alignas(Align) std::byte data[Len + !Len]; + }; template - static constexpr bool in_situ = Len && alignof(Type) <= alignof(storage_type) && sizeof(Type) <= sizeof(storage_type) && std::is_nothrow_move_constructible_v; + static constexpr bool in_situ = Len && alignof(Type) <= Align && sizeof(Type) <= Len &&std::is_nothrow_move_constructible_v; template - [[nodiscard]] static constexpr policy type_to_policy() { - if constexpr(std::is_lvalue_reference_v) { - if constexpr(std::is_const_v>) { - return policy::CREF; + static const void *basic_vtable(const operation op, const basic_any &value, const void *other) { + static_assert(!std::is_same_v && std::is_same_v>, Type>, "Invalid type"); + const Type *element = nullptr; + + if constexpr(in_situ) { + element = value.owner() ? reinterpret_cast(&value.storage) : static_cast(value.instance); + } else { + element = static_cast(value.instance); + } + + switch(op) { + case operation::copy: + if constexpr(std::is_copy_constructible_v) { + static_cast(const_cast(other))->initialize(*element); + } + break; + case operation::move: + if constexpr(in_situ) { + if(value.owner()) { + return new(&static_cast(const_cast(other))->storage) Type{std::move(*const_cast(element))}; + } + } + + return (static_cast(const_cast(other))->instance = std::exchange(const_cast(value).instance, nullptr)); + case operation::transfer: + if constexpr(std::is_move_assignable_v) { + *const_cast(element) = std::move(*static_cast(const_cast(other))); + return other; + } + [[fallthrough]]; + case operation::assign: + if constexpr(std::is_copy_assignable_v) { + *const_cast(element) = *static_cast(other); + return other; + } + break; + case operation::destroy: + if constexpr(in_situ) { + element->~Type(); + } else if constexpr(std::is_array_v) { + delete[] element; } else { - return policy::REF; + delete element; } - } else { - return policy::OWNER; - } - } - - template - [[nodiscard]] static bool compare(const void *lhs, const void *rhs) { - if constexpr(!std::is_function_v && is_equality_comparable_v) { - return *static_cast(lhs) == *static_cast(rhs); - } else { - return lhs == rhs; - } - } - - template - static const void * basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const basic_any &from, [[maybe_unused]] void *to) { - static_assert(std::is_same_v>, Type>, "Invalid type"); - - if constexpr(!std::is_void_v) { - const Type *instance = (in_situ && from.mode == policy::OWNER) - ? ENTT_LAUNDER(reinterpret_cast(&from.storage)) - : static_cast(from.instance); - - switch(op) { - case operation::COPY: - if constexpr(std::is_copy_constructible_v) { - static_cast(to)->emplace(*instance); - } - break; - case operation::MOVE: - if constexpr(in_situ) { - if(from.mode == policy::OWNER) { - return new (&static_cast(to)->storage) Type{std::move(*const_cast(instance))}; - } - } - - return (static_cast(to)->instance = std::exchange(const_cast(from).instance, nullptr)); - case operation::DTOR: - if(from.mode == policy::OWNER) { - if constexpr(in_situ) { - instance->~Type(); - } else if constexpr(std::is_array_v) { - delete[] instance; - } else { - delete instance; - } - } - break; - case operation::COMP: - return compare(instance, (*static_cast(to))->data()) ? to : nullptr; - case operation::ADDR: - if(from.mode == policy::CREF) { - return nullptr; - } - [[fallthrough]]; - case operation::CADDR: - return instance; - case operation::TYPE: - *static_cast(to) = type_id(); - break; + break; + case operation::compare: + if constexpr(!std::is_function_v && !std::is_array_v && is_equality_comparable_v) { + return *element == *static_cast(other) ? other : nullptr; + } else { + return (element == other) ? other : nullptr; } + case operation::get: + return element; } return nullptr; } template - void initialize([[maybe_unused]] Args &&... args) { + void initialize([[maybe_unused]] Args &&...args) { + info = &type_id>>(); + if constexpr(!std::is_void_v) { + vtable = basic_vtable>>; + if constexpr(std::is_lvalue_reference_v) { static_assert(sizeof...(Args) == 1u && (std::is_lvalue_reference_v && ...), "Invalid arguments"); + mode = std::is_const_v> ? policy::cref : policy::ref; instance = (std::addressof(args), ...); - } else if constexpr(in_situ) { - if constexpr(sizeof...(Args) != 0u && std::is_aggregate_v) { - new (&storage) Type{std::forward(args)...}; + } else if constexpr(in_situ>>) { + if constexpr(sizeof...(Args) != 0u && std::is_aggregate_v>>) { + new(&storage) std::remove_cv_t>{std::forward(args)...}; } else { - new (&storage) Type(std::forward(args)...); + new(&storage) std::remove_cv_t>(std::forward(args)...); } } else { - if constexpr(sizeof...(Args) != 0u && std::is_aggregate_v) { - instance = new Type{std::forward(args)...}; + if constexpr(sizeof...(Args) != 0u && std::is_aggregate_v>>) { + instance = new std::remove_cv_t>{std::forward(args)...}; } else { - instance = new Type(std::forward(args)...); + instance = new std::remove_cv_t>(std::forward(args)...); } } } } - basic_any(const basic_any &other, const policy pol) ENTT_NOEXCEPT + basic_any(const basic_any &other, const policy pol) noexcept : instance{other.data()}, + info{other.info}, vtable{other.vtable}, - mode{pol} - {} + mode{pol} {} public: /*! @brief Size of the internal storage. */ @@ -142,11 +160,8 @@ public: static constexpr auto alignment = Align; /*! @brief Default constructor. */ - basic_any() ENTT_NOEXCEPT - : instance{}, - vtable{&basic_vtable}, - mode{policy::OWNER} - {} + constexpr basic_any() noexcept + : basic_any{std::in_place_type} {} /** * @brief Constructs a wrapper by directly initializing the new object. @@ -155,27 +170,14 @@ public: * @param args Parameters to use to construct the instance. */ template - explicit basic_any(std::in_place_type_t, Args &&... args) + explicit basic_any(std::in_place_type_t, Args &&...args) : instance{}, - vtable{&basic_vtable>>}, - mode{type_to_policy()} - { + info{}, + vtable{}, + mode{policy::owner} { initialize(std::forward(args)...); } - /** - * @brief Constructs a wrapper that holds an unmanaged object. - * @tparam Type Type of object to use to initialize the wrapper. - * @param value An instance of an object to use to initialize the wrapper. - */ - template - basic_any(std::reference_wrapper value) ENTT_NOEXCEPT - : basic_any{} - { - // invokes deprecated assignment operator (and avoids issues with vs2017) - *this = value; - } - /** * @brief Constructs a wrapper from a given value. * @tparam Type Type of object to use to initialize the wrapper. @@ -183,40 +185,38 @@ public: */ template, basic_any>>> basic_any(Type &&value) - : instance{}, - vtable{&basic_vtable>}, - mode{policy::OWNER} - { - initialize>(std::forward(value)); - } + : basic_any{std::in_place_type>, std::forward(value)} {} /** * @brief Copy constructor. * @param other The instance to copy from. */ basic_any(const basic_any &other) - : instance{}, - vtable{&basic_vtable}, - mode{policy::OWNER} - { - other.vtable(operation::COPY, other, this); + : basic_any{} { + if(other.vtable) { + other.vtable(operation::copy, other, this); + } } /** * @brief Move constructor. * @param other The instance to move from. */ - basic_any(basic_any &&other) ENTT_NOEXCEPT + basic_any(basic_any &&other) noexcept : instance{}, + info{other.info}, vtable{other.vtable}, - mode{other.mode} - { - vtable(operation::MOVE, other, this); + mode{other.mode} { + if(other.vtable) { + other.vtable(operation::move, other, this); + } } /*! @brief Frees the internal storage, whatever it means. */ ~basic_any() { - vtable(operation::DTOR, *this, nullptr); + if(vtable && owner()) { + vtable(operation::destroy, *this, nullptr); + } } /** @@ -224,9 +224,13 @@ public: * @param other The instance to copy from. * @return This any object. */ - basic_any & operator=(const basic_any &other) { + basic_any &operator=(const basic_any &other) { reset(); - other.vtable(operation::COPY, other, this); + + if(other.vtable) { + other.vtable(operation::copy, other, this); + } + return *this; } @@ -235,23 +239,16 @@ public: * @param other The instance to move from. * @return This any object. */ - basic_any & operator=(basic_any &&other) ENTT_NOEXCEPT { - std::exchange(vtable, other.vtable)(operation::DTOR, *this, nullptr); - other.vtable(operation::MOVE, other, this); - mode = other.mode; - return *this; - } + basic_any &operator=(basic_any &&other) noexcept { + reset(); + + if(other.vtable) { + other.vtable(operation::move, other, this); + info = other.info; + vtable = other.vtable; + mode = other.mode; + } - /** - * @brief Value assignment operator. - * @tparam Type Type of object to use to initialize the wrapper. - * @param value An instance of an object to use to initialize the wrapper. - * @return This any object. - */ - template - [[deprecated("Use std::in_place_type, entt::make_any, emplace or forward_as_any instead")]] - basic_any & operator=(std::reference_wrapper value) ENTT_NOEXCEPT { - emplace(value.get()); return *this; } @@ -269,26 +266,45 @@ public: } /** - * @brief Returns the type of the contained object. - * @return The type of the contained object, if any. + * @brief Returns the object type if any, `type_id()` otherwise. + * @return The object type if any, `type_id()` otherwise. */ - [[nodiscard]] type_info type() const ENTT_NOEXCEPT { - type_info info{}; - vtable(operation::TYPE, *this, &info); - return info; + [[nodiscard]] const type_info &type() const noexcept { + return *info; } /** * @brief Returns an opaque pointer to the contained instance. * @return An opaque pointer the contained instance, if any. */ - [[nodiscard]] const void * data() const ENTT_NOEXCEPT { - return vtable(operation::CADDR, *this, nullptr); + [[nodiscard]] const void *data() const noexcept { + return vtable ? vtable(operation::get, *this, nullptr) : nullptr; } - /*! @copydoc data */ - [[nodiscard]] void * data() ENTT_NOEXCEPT { - return const_cast(vtable(operation::ADDR, *this, nullptr)); + /** + * @brief Returns an opaque pointer to the contained instance. + * @param req Expected type. + * @return An opaque pointer the contained instance, if any. + */ + [[nodiscard]] const void *data(const type_info &req) const noexcept { + return *info == req ? data() : nullptr; + } + + /** + * @brief Returns an opaque pointer to the contained instance. + * @return An opaque pointer the contained instance, if any. + */ + [[nodiscard]] void *data() noexcept { + return mode == policy::cref ? nullptr : const_cast(std::as_const(*this).data()); + } + + /** + * @brief Returns an opaque pointer to the contained instance. + * @param req Expected type. + * @return An opaque pointer the contained instance, if any. + */ + [[nodiscard]] void *data(const type_info &req) noexcept { + return mode == policy::cref ? nullptr : const_cast(std::as_const(*this).data(req)); } /** @@ -298,24 +314,56 @@ public: * @param args Parameters to use to construct the instance. */ template - void emplace(Args &&... args) { - std::exchange(vtable, &basic_vtable>>)(operation::DTOR, *this, nullptr); - mode = type_to_policy(); + void emplace(Args &&...args) { + reset(); initialize(std::forward(args)...); } + /** + * @brief Assigns a value to the contained object without replacing it. + * @param other The value to assign to the contained object. + * @return True in case of success, false otherwise. + */ + bool assign(const basic_any &other) { + if(vtable && mode != policy::cref && *info == *other.info) { + return (vtable(operation::assign, *this, other.data()) != nullptr); + } + + return false; + } + + /*! @copydoc assign */ + bool assign(basic_any &&other) { + if(vtable && mode != policy::cref && *info == *other.info) { + if(auto *val = other.data(); val) { + return (vtable(operation::transfer, *this, val) != nullptr); + } else { + return (vtable(operation::assign, *this, std::as_const(other).data()) != nullptr); + } + } + + return false; + } + /*! @brief Destroys contained object */ void reset() { - std::exchange(vtable, &basic_vtable)(operation::DTOR, *this, nullptr); - mode = policy::OWNER; + if(vtable && owner()) { + vtable(operation::destroy, *this, nullptr); + } + + // unnecessary but it helps to detect nasty bugs + ENTT_ASSERT((instance = nullptr) == nullptr, ""); + info = &type_id(); + vtable = nullptr; + mode = policy::owner; } /** * @brief Returns false if a wrapper is empty, true otherwise. * @return False if the wrapper is empty, true otherwise. */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { - return !(vtable(operation::CADDR, *this, nullptr) == nullptr); + [[nodiscard]] explicit operator bool() const noexcept { + return vtable != nullptr; } /** @@ -323,53 +371,54 @@ public: * @param other Wrapper with which to compare. * @return False if the two objects differ in their content, true otherwise. */ - bool operator==(const basic_any &other) const ENTT_NOEXCEPT { - const basic_any *trampoline = &other; - return type() == other.type() && (vtable(operation::COMP, *this, &trampoline) || !other.data()); + [[nodiscard]] bool operator==(const basic_any &other) const noexcept { + if(vtable && *info == *other.info) { + return (vtable(operation::compare, *this, other.data()) != nullptr); + } + + return (!vtable && !other.vtable); + } + + /** + * @brief Checks if two wrappers differ in their content. + * @param other Wrapper with which to compare. + * @return True if the two objects differ in their content, false otherwise. + */ + [[nodiscard]] bool operator!=(const basic_any &other) const noexcept { + return !(*this == other); } /** * @brief Aliasing constructor. * @return A wrapper that shares a reference to an unmanaged object. */ - [[nodiscard]] basic_any as_ref() ENTT_NOEXCEPT { - return basic_any{*this, (mode == policy::CREF ? policy::CREF : policy::REF)}; + [[nodiscard]] basic_any as_ref() noexcept { + return basic_any{*this, (mode == policy::cref ? policy::cref : policy::ref)}; } /*! @copydoc as_ref */ - [[nodiscard]] basic_any as_ref() const ENTT_NOEXCEPT { - return basic_any{*this, policy::CREF}; + [[nodiscard]] basic_any as_ref() const noexcept { + return basic_any{*this, policy::cref}; } /** * @brief Returns true if a wrapper owns its object, false otherwise. * @return True if the wrapper owns its object, false otherwise. */ - [[nodiscard]] bool owner() const ENTT_NOEXCEPT { - return (mode == policy::OWNER); + [[nodiscard]] bool owner() const noexcept { + return (mode == policy::owner); } private: - union { const void *instance; storage_type storage; }; + union { + const void *instance; + storage_type storage; + }; + const type_info *info; vtable_type *vtable; policy mode; }; - -/** - * @brief Checks if two wrappers differ in their content. - * @tparam Len Size of the storage reserved for the small buffer optimization. - * @tparam Align Alignment requirement. - * @param lhs A wrapper, either empty or not. - * @param rhs A wrapper, either empty or not. - * @return True if the two wrappers differ in their content, false otherwise. - */ -template -[[nodiscard]] inline bool operator!=(const basic_any &lhs, const basic_any &rhs) ENTT_NOEXCEPT { - return !(lhs == rhs); -} - - /** * @brief Performs type-safe access to the contained object. * @tparam Type Type to which conversion is required. @@ -379,48 +428,56 @@ template * @return The element converted to the requested type. */ template -Type any_cast(const basic_any &data) ENTT_NOEXCEPT { - const auto * const instance = any_cast>(&data); +Type any_cast(const basic_any &data) noexcept { + const auto *const instance = any_cast>(&data); ENTT_ASSERT(instance, "Invalid instance"); return static_cast(*instance); } - /*! @copydoc any_cast */ template -Type any_cast(basic_any &data) ENTT_NOEXCEPT { +Type any_cast(basic_any &data) noexcept { // forces const on non-reference types to make them work also with wrappers for const references - auto * const instance = any_cast>(&data); + auto *const instance = any_cast>(&data); ENTT_ASSERT(instance, "Invalid instance"); return static_cast(*instance); } +/*! @copydoc any_cast */ +template +Type any_cast(basic_any &&data) noexcept { + if constexpr(std::is_copy_constructible_v>>) { + if(auto *const instance = any_cast>(&data); instance) { + return static_cast(std::move(*instance)); + } else { + return any_cast(data); + } + } else { + auto *const instance = any_cast>(&data); + ENTT_ASSERT(instance, "Invalid instance"); + return static_cast(std::move(*instance)); + } +} /*! @copydoc any_cast */ template -Type any_cast(basic_any &&data) ENTT_NOEXCEPT { - // forces const on non-reference types to make them work also with wrappers for const references - auto * const instance = any_cast>(&data); - ENTT_ASSERT(instance, "Invalid instance"); - return static_cast(std::move(*instance)); +const Type *any_cast(const basic_any *data) noexcept { + const auto &info = type_id>(); + return static_cast(data->data(info)); } - /*! @copydoc any_cast */ template -const Type * any_cast(const basic_any *data) ENTT_NOEXCEPT { - return (data->type() == type_id() ? static_cast(data->data()) : nullptr); +Type *any_cast(basic_any *data) noexcept { + if constexpr(std::is_const_v) { + // last attempt to make wrappers for const references return their values + return any_cast(&std::as_const(*data)); + } else { + const auto &info = type_id>(); + return static_cast(data->data(info)); + } } - -/*! @copydoc any_cast */ -template -Type * any_cast(basic_any *data) ENTT_NOEXCEPT { - // last attempt to make wrappers for const references return their values - return (data->type() == type_id() ? static_cast(static_cast, Type> *>(data)->data()) : nullptr); -} - - /** * @brief Constructs a wrapper from a given type, passing it all arguments. * @tparam Type Type of object to use to initialize the wrapper. @@ -431,11 +488,10 @@ Type * any_cast(basic_any *data) ENTT_NOEXCEPT { * @return A properly initialized wrapper for an object of the given type. */ template::length, std::size_t Align = basic_any::alignment, typename... Args> -basic_any make_any(Args &&... args) { +basic_any make_any(Args &&...args) { return basic_any{std::in_place_type, std::forward(args)...}; } - /** * @brief Forwards its argument and avoids copies for lvalue references. * @tparam Len Size of the storage reserved for the small buffer optimization. @@ -446,11 +502,9 @@ basic_any make_any(Args &&... args) { */ template::length, std::size_t Align = basic_any::alignment, typename Type> basic_any forward_as_any(Type &&value) { - return basic_any{std::in_place_type, std::decay_t, Type>>, std::forward(value)}; -} - - + return basic_any{std::in_place_type, std::forward(value)}; } +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/core/attribute.h b/LiteLoader/third-party/include/entt/core/attribute.h index 4a7a092..b1d0503 100644 --- a/LiteLoader/third-party/include/entt/core/attribute.h +++ b/LiteLoader/third-party/include/entt/core/attribute.h @@ -1,33 +1,30 @@ #ifndef ENTT_CORE_ATTRIBUTE_H #define ENTT_CORE_ATTRIBUTE_H - #ifndef ENTT_EXPORT -# if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER -# define ENTT_EXPORT __declspec(dllexport) -# define ENTT_IMPORT __declspec(dllimport) -# define ENTT_HIDDEN -# elif defined __GNUC__ && __GNUC__ >= 4 -# define ENTT_EXPORT __attribute__((visibility("default"))) -# define ENTT_IMPORT __attribute__((visibility("default"))) -# define ENTT_HIDDEN __attribute__((visibility("hidden"))) -# else /* Unsupported compiler */ -# define ENTT_EXPORT -# define ENTT_IMPORT -# define ENTT_HIDDEN -# endif +# if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER +# define ENTT_EXPORT __declspec(dllexport) +# define ENTT_IMPORT __declspec(dllimport) +# define ENTT_HIDDEN +# elif defined __GNUC__ && __GNUC__ >= 4 +# define ENTT_EXPORT __attribute__((visibility("default"))) +# define ENTT_IMPORT __attribute__((visibility("default"))) +# define ENTT_HIDDEN __attribute__((visibility("hidden"))) +# else /* Unsupported compiler */ +# define ENTT_EXPORT +# define ENTT_IMPORT +# define ENTT_HIDDEN +# endif #endif - #ifndef ENTT_API -# if defined ENTT_API_EXPORT -# define ENTT_API ENTT_EXPORT -# elif defined ENTT_API_IMPORT -# define ENTT_API ENTT_IMPORT -# else /* No API */ -# define ENTT_API -# endif +# if defined ENTT_API_EXPORT +# define ENTT_API ENTT_EXPORT +# elif defined ENTT_API_IMPORT +# define ENTT_API ENTT_IMPORT +# else /* No API */ +# define ENTT_API +# endif #endif - #endif diff --git a/LiteLoader/third-party/include/entt/core/family.hpp b/LiteLoader/third-party/include/entt/core/family.hpp index 8fa4a45..642ae2f 100644 --- a/LiteLoader/third-party/include/entt/core/family.hpp +++ b/LiteLoader/third-party/include/entt/core/family.hpp @@ -1,14 +1,11 @@ #ifndef ENTT_CORE_FAMILY_HPP #define ENTT_CORE_FAMILY_HPP - -#include "third-party/include/entt/config/config.h" +#include "../config/config.h" #include "fwd.hpp" - namespace entt { - /** * @brief Dynamic identifier generator. * @@ -22,16 +19,14 @@ class family { public: /*! @brief Unsigned integer type. */ - using family_type = id_type; + using value_type = id_type; /*! @brief Statically generated unique identifier for the given type. */ template // at the time I'm writing, clang crashes during compilation if auto is used instead of family_type - inline static const family_type type = identifier++; + inline static const value_type value = identifier++; }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/core/fwd.hpp b/LiteLoader/third-party/include/entt/core/fwd.hpp index 5138af1..472ed12 100644 --- a/LiteLoader/third-party/include/entt/core/fwd.hpp +++ b/LiteLoader/third-party/include/entt/core/fwd.hpp @@ -1,27 +1,20 @@ #ifndef ENTT_CORE_FWD_HPP #define ENTT_CORE_FWD_HPP - -#include -#include "third-party/include/entt/config/config.h" - +#include +#include "../config/config.h" namespace entt { - -template)> +template class basic_any; - /*! @brief Alias declaration for type identifiers. */ using id_type = ENTT_ID_TYPE; - /*! @brief Alias declaration for the most common use case. */ using any = basic_any<>; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/core/hashed_string.hpp b/LiteLoader/third-party/include/entt/core/hashed_string.hpp index 3cf9e1e..02a50a9 100644 --- a/LiteLoader/third-party/include/entt/core/hashed_string.hpp +++ b/LiteLoader/third-party/include/entt/core/hashed_string.hpp @@ -1,29 +1,22 @@ #ifndef ENTT_CORE_HASHED_STRING_HPP #define ENTT_CORE_HASHED_STRING_HPP - #include #include -#include "third-party/include/entt/config/config.h" #include "fwd.hpp" - namespace entt { - /** * @cond TURN_OFF_DOXYGEN * Internal details not to be documented. */ - namespace internal { - template struct fnv1a_traits; - template<> struct fnv1a_traits { using type = std::uint32_t; @@ -31,7 +24,6 @@ struct fnv1a_traits { static constexpr std::uint32_t prime = 16777619; }; - template<> struct fnv1a_traits { using type = std::uint64_t; @@ -39,84 +31,101 @@ struct fnv1a_traits { static constexpr std::uint64_t prime = 1099511628211ull; }; +template +struct basic_hashed_string { + using value_type = Char; + using size_type = std::size_t; + using hash_type = id_type; -} + const value_type *repr; + size_type length; + hash_type hash; +}; +} // namespace internal /** * Internal details not to be documented. * @endcond */ - /** * @brief Zero overhead unique identifier. * * A hashed string is a compile-time tool that allows users to use - * human-readable identifers in the codebase while using their numeric + * human-readable identifiers in the codebase while using their numeric * counterparts at runtime.
* Because of that, a hashed string can also be used in constant expressions if * required. * + * @warning + * This class doesn't take ownership of user-supplied strings nor does it make a + * copy of them. + * * @tparam Char Character type. */ template -class basic_hashed_string { - using traits_type = internal::fnv1a_traits; +class basic_hashed_string: internal::basic_hashed_string { + using base_type = internal::basic_hashed_string; + using hs_traits = internal::fnv1a_traits; struct const_wrapper { // non-explicit constructor on purpose - constexpr const_wrapper(const Char *curr) ENTT_NOEXCEPT: str{curr} {} - const Char *str; + constexpr const_wrapper(const Char *str) noexcept + : repr{str} {} + + const Char *repr; }; // Fowler–Noll–Vo hash function v. 1a - the good - [[nodiscard]] static constexpr id_type helper(const Char *curr) ENTT_NOEXCEPT { - auto value = traits_type::offset; + [[nodiscard]] static constexpr auto helper(const Char *str) noexcept { + base_type base{str, 0u, hs_traits::offset}; - while(*curr != 0) { - value = (value ^ static_cast(*(curr++))) * traits_type::prime; + for(; str[base.length]; ++base.length) { + base.hash = (base.hash ^ static_cast(str[base.length])) * hs_traits::prime; } - return value; + return base; + } + + // Fowler–Noll–Vo hash function v. 1a - the good + [[nodiscard]] static constexpr auto helper(const Char *str, const std::size_t len) noexcept { + base_type base{str, len, hs_traits::offset}; + + for(size_type pos{}; pos < len; ++pos) { + base.hash = (base.hash ^ static_cast(str[pos])) * hs_traits::prime; + } + + return base; } public: /*! @brief Character type. */ - using value_type = Char; + using value_type = typename base_type::value_type; /*! @brief Unsigned integer type. */ - using hash_type = id_type; + using size_type = typename base_type::size_type; + /*! @brief Unsigned integer type. */ + using hash_type = typename base_type::hash_type; /** * @brief Returns directly the numeric representation of a string view. - * @param str Human-readable identifer. - * @param size Length of the string to hash. + * @param str Human-readable identifier. + * @param len Length of the string to hash. * @return The numeric representation of the string. */ - [[nodiscard]] static constexpr hash_type value(const value_type *str, std::size_t size) ENTT_NOEXCEPT { - id_type partial{traits_type::offset}; - while(size--) { partial = (partial^(str++)[0])*traits_type::prime; } - return partial; + [[nodiscard]] static constexpr hash_type value(const value_type *str, const size_type len) noexcept { + return basic_hashed_string{str, len}; } /** * @brief Returns directly the numeric representation of a string. - * - * Forcing template resolution avoids implicit conversions. An - * human-readable identifier can be anything but a plain, old bunch of - * characters.
- * Example of use: - * @code{.cpp} - * const auto value = basic_hashed_string::to_value("my.png"); - * @endcode - * * @tparam N Number of characters of the identifier. - * @param str Human-readable identifer. + * @param str Human-readable identifier. * @return The numeric representation of the string. */ template - [[nodiscard]] static constexpr hash_type value(const value_type (&str)[N]) ENTT_NOEXCEPT { - return helper(str); + [[nodiscard]] static constexpr hash_type value(const value_type (&str)[N]) noexcept { + return basic_hashed_string{str}; } /** @@ -124,97 +133,98 @@ public: * @param wrapper Helps achieving the purpose by relying on overloading. * @return The numeric representation of the string. */ - [[nodiscard]] static hash_type value(const_wrapper wrapper) ENTT_NOEXCEPT { - return helper(wrapper.str); + [[nodiscard]] static constexpr hash_type value(const_wrapper wrapper) noexcept { + return basic_hashed_string{wrapper}; } /*! @brief Constructs an empty hashed string. */ - constexpr basic_hashed_string() ENTT_NOEXCEPT - : str{nullptr}, hash{} - {} + constexpr basic_hashed_string() noexcept + : base_type{} {} + + /** + * @brief Constructs a hashed string from a string view. + * @param str Human-readable identifier. + * @param len Length of the string to hash. + */ + constexpr basic_hashed_string(const value_type *str, const size_type len) noexcept + : base_type{helper(str, len)} {} /** * @brief Constructs a hashed string from an array of const characters. - * - * Forcing template resolution avoids implicit conversions. An - * human-readable identifier can be anything but a plain, old bunch of - * characters.
- * Example of use: - * @code{.cpp} - * basic_hashed_string hs{"my.png"}; - * @endcode - * * @tparam N Number of characters of the identifier. - * @param curr Human-readable identifer. + * @param str Human-readable identifier. */ template - constexpr basic_hashed_string(const value_type (&curr)[N]) ENTT_NOEXCEPT - : str{curr}, hash{helper(curr)} - {} + constexpr basic_hashed_string(const value_type (&str)[N]) noexcept + : base_type{helper(str)} {} /** * @brief Explicit constructor on purpose to avoid constructing a hashed * string directly from a `const value_type *`. + * + * @warning + * The lifetime of the string is not extended nor is it copied. + * * @param wrapper Helps achieving the purpose by relying on overloading. */ - explicit constexpr basic_hashed_string(const_wrapper wrapper) ENTT_NOEXCEPT - : str{wrapper.str}, hash{helper(wrapper.str)} - {} + explicit constexpr basic_hashed_string(const_wrapper wrapper) noexcept + : base_type{helper(wrapper.repr)} {} + + /** + * @brief Returns the size a hashed string. + * @return The size of the hashed string. + */ + [[nodiscard]] constexpr size_type size() const noexcept { + return base_type::length; + } /** * @brief Returns the human-readable representation of a hashed string. - * @return The string used to initialize the instance. + * @return The string used to initialize the hashed string. */ - [[nodiscard]] constexpr const value_type * data() const ENTT_NOEXCEPT { - return str; + [[nodiscard]] constexpr const value_type *data() const noexcept { + return base_type::repr; } /** * @brief Returns the numeric representation of a hashed string. - * @return The numeric representation of the instance. + * @return The numeric representation of the hashed string. */ - [[nodiscard]] constexpr hash_type value() const ENTT_NOEXCEPT { - return hash; + [[nodiscard]] constexpr hash_type value() const noexcept { + return base_type::hash; } /*! @copydoc data */ - [[nodiscard]] constexpr operator const value_type *() const ENTT_NOEXCEPT { return data(); } + [[nodiscard]] constexpr operator const value_type *() const noexcept { + return data(); + } /** * @brief Returns the numeric representation of a hashed string. - * @return The numeric representation of the instance. + * @return The numeric representation of the hashed string. */ - [[nodiscard]] constexpr operator hash_type() const ENTT_NOEXCEPT { return value(); } - - /** - * @brief Compares two hashed strings. - * @param other Hashed string with which to compare. - * @return True if the two hashed strings are identical, false otherwise. - */ - [[nodiscard]] constexpr bool operator==(const basic_hashed_string &other) const ENTT_NOEXCEPT { - return hash == other.hash; + [[nodiscard]] constexpr operator hash_type() const noexcept { + return value(); } - -private: - const value_type *str; - hash_type hash; }; - /** * @brief Deduction guide. - * - * It allows to deduce the character type of the hashed string directly from a - * human-readable identifer provided to the constructor. - * + * @tparam Char Character type. + * @param str Human-readable identifier. + * @param len Length of the string to hash. + */ +template +basic_hashed_string(const Char *str, const std::size_t len) -> basic_hashed_string; + +/** + * @brief Deduction guide. * @tparam Char Character type. * @tparam N Number of characters of the identifier. - * @param str Human-readable identifer. + * @param str Human-readable identifier. */ template -basic_hashed_string(const Char (&str)[N]) --> basic_hashed_string; - +basic_hashed_string(const Char (&str)[N]) -> basic_hashed_string; /** * @brief Compares two hashed strings. @@ -224,46 +234,101 @@ basic_hashed_string(const Char (&str)[N]) * @return True if the two hashed strings are identical, false otherwise. */ template -[[nodiscard]] constexpr bool operator!=(const basic_hashed_string &lhs, const basic_hashed_string &rhs) ENTT_NOEXCEPT { +[[nodiscard]] constexpr bool operator==(const basic_hashed_string &lhs, const basic_hashed_string &rhs) noexcept { + return lhs.value() == rhs.value(); +} + +/** + * @brief Compares two hashed strings. + * @tparam Char Character type. + * @param lhs A valid hashed string. + * @param rhs A valid hashed string. + * @return True if the two hashed strings differ, false otherwise. + */ +template +[[nodiscard]] constexpr bool operator!=(const basic_hashed_string &lhs, const basic_hashed_string &rhs) noexcept { return !(lhs == rhs); } +/** + * @brief Compares two hashed strings. + * @tparam Char Character type. + * @param lhs A valid hashed string. + * @param rhs A valid hashed string. + * @return True if the first element is less than the second, false otherwise. + */ +template +[[nodiscard]] constexpr bool operator<(const basic_hashed_string &lhs, const basic_hashed_string &rhs) noexcept { + return lhs.value() < rhs.value(); +} + +/** + * @brief Compares two hashed strings. + * @tparam Char Character type. + * @param lhs A valid hashed string. + * @param rhs A valid hashed string. + * @return True if the first element is less than or equal to the second, false + * otherwise. + */ +template +[[nodiscard]] constexpr bool operator<=(const basic_hashed_string &lhs, const basic_hashed_string &rhs) noexcept { + return !(rhs < lhs); +} + +/** + * @brief Compares two hashed strings. + * @tparam Char Character type. + * @param lhs A valid hashed string. + * @param rhs A valid hashed string. + * @return True if the first element is greater than the second, false + * otherwise. + */ +template +[[nodiscard]] constexpr bool operator>(const basic_hashed_string &lhs, const basic_hashed_string &rhs) noexcept { + return rhs < lhs; +} + +/** + * @brief Compares two hashed strings. + * @tparam Char Character type. + * @param lhs A valid hashed string. + * @param rhs A valid hashed string. + * @return True if the first element is greater than or equal to the second, + * false otherwise. + */ +template +[[nodiscard]] constexpr bool operator>=(const basic_hashed_string &lhs, const basic_hashed_string &rhs) noexcept { + return !(lhs < rhs); +} /*! @brief Aliases for common character types. */ using hashed_string = basic_hashed_string; - /*! @brief Aliases for common character types. */ using hashed_wstring = basic_hashed_string; - inline namespace literals { - /** * @brief User defined literal for hashed strings. * @param str The literal without its suffix. * @return A properly initialized hashed string. */ -[[nodiscard]] constexpr entt::hashed_string operator"" _hs(const char *str, std::size_t) ENTT_NOEXCEPT { - return entt::hashed_string{str}; +[[nodiscard]] constexpr hashed_string operator"" _hs(const char *str, std::size_t) noexcept { + return hashed_string{str}; } - /** * @brief User defined literal for hashed wstrings. * @param str The literal without its suffix. * @return A properly initialized hashed wstring. */ -[[nodiscard]] constexpr entt::hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_NOEXCEPT { - return entt::hashed_wstring{str}; +[[nodiscard]] constexpr hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) noexcept { + return hashed_wstring{str}; } +} // namespace literals -} - - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/core/ident.hpp b/LiteLoader/third-party/include/entt/core/ident.hpp index fcae3c5..2ff6026 100644 --- a/LiteLoader/third-party/include/entt/core/ident.hpp +++ b/LiteLoader/third-party/include/entt/core/ident.hpp @@ -1,64 +1,35 @@ #ifndef ENTT_CORE_IDENT_HPP #define ENTT_CORE_IDENT_HPP - #include -#include #include -#include "third-party/include/entt/config/config.h" +#include #include "fwd.hpp" #include "type_traits.hpp" - namespace entt { - /** - * @brief Types identifiers. - * - * Variable template used to generate identifiers at compile-time for the given - * types. Use the `get` member function to know what's the identifier associated - * to the specific type. - * - * @note - * Identifiers are constant expression and can be used in any context where such - * an expression is required. As an example: - * @code{.cpp} - * using id = entt::identifier; - * - * switch(a_type_identifier) { - * case id::type: - * // ... - * break; - * case id::type: - * // ... - * break; - * default: - * // ... - * } - * @endcode - * - * @tparam Types List of types for which to generate identifiers. + * @brief Type integral identifiers. + * @tparam Type List of types for which to generate identifiers. */ -template -class identifier { - template - [[nodiscard]] static constexpr id_type get(std::index_sequence) { - static_assert(std::disjunction_v...>, "Invalid type"); - return (0 + ... + (std::is_same_v...>>> ? id_type{Index} : id_type{})); +template +class ident { + template + [[nodiscard]] static constexpr id_type get(std::index_sequence) noexcept { + static_assert((std::is_same_v || ...), "Invalid type"); + return (0 + ... + (std::is_same_v...>>> ? id_type{Index} : id_type{})); } public: /*! @brief Unsigned integer type. */ - using identifier_type = id_type; + using value_type = id_type; /*! @brief Statically generated unique identifier for the given type. */ - template - static constexpr identifier_type type = get>(std::index_sequence_for{}); + template + static constexpr value_type value = get>(std::index_sequence_for{}); }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/core/monostate.hpp b/LiteLoader/third-party/include/entt/core/monostate.hpp index e42f920..88225db 100644 --- a/LiteLoader/third-party/include/entt/core/monostate.hpp +++ b/LiteLoader/third-party/include/entt/core/monostate.hpp @@ -1,14 +1,11 @@ #ifndef ENTT_CORE_MONOSTATE_HPP #define ENTT_CORE_MONOSTATE_HPP - -#include "third-party/include/entt/config/config.h" +#include "../config/config.h" #include "fwd.hpp" - namespace entt { - /** * @brief Minimal implementation of the monostate pattern. * @@ -28,7 +25,7 @@ struct monostate { * @param val User data to assign to the given key. */ template - void operator=(Type val) const ENTT_NOEXCEPT { + void operator=(Type val) const noexcept { value = val; } @@ -38,7 +35,7 @@ struct monostate { * @return Stored value, if any. */ template - operator Type() const ENTT_NOEXCEPT { + operator Type() const noexcept { return value; } @@ -47,7 +44,6 @@ private: inline static ENTT_MAYBE_ATOMIC(Type) value{}; }; - /** * @brief Helper variable template. * @tparam Value Value used to differentiate between different variables. @@ -55,8 +51,6 @@ private: template inline monostate monostate_v = {}; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/core/type_info.hpp b/LiteLoader/third-party/include/entt/core/type_info.hpp index b3b16a5..bcf4977 100644 --- a/LiteLoader/third-party/include/entt/core/type_info.hpp +++ b/LiteLoader/third-party/include/entt/core/type_info.hpp @@ -1,40 +1,35 @@ #ifndef ENTT_CORE_TYPE_INFO_HPP #define ENTT_CORE_TYPE_INFO_HPP - #include #include -#include "third-party/include/entt/config/config.h" -#include "attribute.h" -#include "hashed_string.hpp" +#include +#include "../config/config.h" +#include "../core/attribute.h" #include "fwd.hpp" - +#include "hashed_string.hpp" namespace entt { - /** * @cond TURN_OFF_DOXYGEN * Internal details not to be documented. */ - namespace internal { - -struct ENTT_API type_seq final { - [[nodiscard]] static id_type next() ENTT_NOEXCEPT { +struct ENTT_API type_index final { + [[nodiscard]] static id_type next() noexcept { static ENTT_MAYBE_ATOMIC(id_type) value{}; return value++; } }; - template -[[nodiscard]] constexpr auto stripped_type_name() ENTT_NOEXCEPT { +[[nodiscard]] constexpr auto stripped_type_name() noexcept { #if defined ENTT_PRETTY_FUNCTION std::string_view pretty_function{ENTT_PRETTY_FUNCTION}; - auto first = pretty_function.find_first_not_of(' ', pretty_function.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX)+1); + auto first = pretty_function.find_first_not_of(' ', pretty_function.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1); auto value = pretty_function.substr(first, pretty_function.find_last_of(ENTT_PRETTY_FUNCTION_SUFFIX) - first); return value; #else @@ -42,67 +37,61 @@ template #endif } - template().find_first_of('.')> -[[nodiscard]] static constexpr std::string_view type_name(int) ENTT_NOEXCEPT { +[[nodiscard]] static constexpr std::string_view type_name(int) noexcept { constexpr auto value = stripped_type_name(); return value; } - template -[[nodiscard]] static std::string_view type_name(char) ENTT_NOEXCEPT { +[[nodiscard]] static std::string_view type_name(char) noexcept { static const auto value = stripped_type_name(); return value; } - template().find_first_of('.')> -[[nodiscard]] static constexpr id_type type_hash(int) ENTT_NOEXCEPT { +[[nodiscard]] static constexpr id_type type_hash(int) noexcept { constexpr auto stripped = stripped_type_name(); constexpr auto value = hashed_string::value(stripped.data(), stripped.size()); return value; } - template -[[nodiscard]] static id_type type_hash(char) ENTT_NOEXCEPT { +[[nodiscard]] static id_type type_hash(char) noexcept { static const auto value = [](const auto stripped) { return hashed_string::value(stripped.data(), stripped.size()); }(stripped_type_name()); return value; } - -} - +} // namespace internal /** * Internal details not to be documented. * @endcond */ - /** * @brief Type sequential identifier. * @tparam Type Type for which to generate a sequential identifier. */ template -struct ENTT_API type_seq final { +struct ENTT_API type_index final { /** * @brief Returns the sequential identifier of a given type. * @return The sequential identifier of a given type. */ - [[nodiscard]] static id_type value() ENTT_NOEXCEPT { - static const id_type value = internal::type_seq::next(); + [[nodiscard]] static id_type value() noexcept { + static const id_type value = internal::type_index::next(); return value; } /*! @copydoc value */ - [[nodiscard]] constexpr operator id_type() const ENTT_NOEXCEPT { return value(); } + [[nodiscard]] constexpr operator id_type() const noexcept { + return value(); + } }; - /** * @brief Type hash. * @tparam Type Type for which to generate a hash value. @@ -114,19 +103,20 @@ struct type_hash final { * @return The numeric representation of the given type. */ #if defined ENTT_PRETTY_FUNCTION - [[nodiscard]] static constexpr id_type value() ENTT_NOEXCEPT { + [[nodiscard]] static constexpr id_type value() noexcept { return internal::type_hash(0); #else - [[nodiscard]] static constexpr id_type value() ENTT_NOEXCEPT { - return type_seq::value(); + [[nodiscard]] static constexpr id_type value() noexcept { + return type_index::value(); #endif } /*! @copydoc value */ - [[nodiscard]] constexpr operator id_type() const ENTT_NOEXCEPT { return value(); } + [[nodiscard]] constexpr operator id_type() const noexcept { + return value(); + } }; - /** * @brief Type name. * @tparam Type Type for which to generate a name. @@ -137,124 +127,148 @@ struct type_name final { * @brief Returns the name of a given type. * @return The name of the given type. */ - [[nodiscard]] static constexpr std::string_view value() ENTT_NOEXCEPT { + [[nodiscard]] static constexpr std::string_view value() noexcept { return internal::type_name(0); } /*! @copydoc value */ - [[nodiscard]] constexpr operator std::string_view() const ENTT_NOEXCEPT { return value(); } + [[nodiscard]] constexpr operator std::string_view() const noexcept { + return value(); + } }; - /*! @brief Implementation specific information about a type. */ -class type_info final { - template - friend type_info type_id() ENTT_NOEXCEPT; - - type_info(id_type seq_v, id_type hash_v, std::string_view name_v) ENTT_NOEXCEPT - : seq_value{seq_v}, - hash_value{hash_v}, - name_value{name_v} - {} - -public: - /*! @brief Default constructor. */ - type_info() ENTT_NOEXCEPT - : type_info({}, {}, {}) - {} - - /*! @brief Default copy constructor. */ - type_info(const type_info &) ENTT_NOEXCEPT = default; - /*! @brief Default move constructor. */ - type_info(type_info &&) ENTT_NOEXCEPT = default; +struct type_info final { + /** + * @brief Constructs a type info object for a given type. + * @tparam Type Type for which to construct a type info object. + */ + template + constexpr type_info(std::in_place_type_t) noexcept + : seq{type_index>>::value()}, + identifier{type_hash>>::value()}, + alias{type_name>>::value()} {} /** - * @brief Default copy assignment operator. - * @return This type info object. + * @brief Type index. + * @return Type index. */ - type_info & operator=(const type_info &) ENTT_NOEXCEPT = default; - - /** - * @brief Default move assignment operator. - * @return This type info object. - */ - type_info & operator=(type_info &&) ENTT_NOEXCEPT = default; - - /** - * @brief Checks if a type info object is properly initialized. - * @return True if the object is properly initialized, false otherwise. - */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { - return name_value.data() != nullptr; - } - - /** - * @brief Type sequential identifier. - * @return Type sequential identifier. - */ - [[nodiscard]] id_type seq() const ENTT_NOEXCEPT { - return seq_value; + [[nodiscard]] constexpr id_type index() const noexcept { + return seq; } /** * @brief Type hash. * @return Type hash. */ - [[nodiscard]] id_type hash() const ENTT_NOEXCEPT { - return hash_value; + [[nodiscard]] constexpr id_type hash() const noexcept { + return identifier; } /** * @brief Type name. * @return Type name. */ - [[nodiscard]] std::string_view name() const ENTT_NOEXCEPT { - return name_value; - } - - /** - * @brief Compares the contents of two type info objects. - * @param other Object with which to compare. - * @return False if the two contents differ, true otherwise. - */ - [[nodiscard]] bool operator==(const type_info &other) const ENTT_NOEXCEPT { - return hash_value == other.hash_value; + [[nodiscard]] constexpr std::string_view name() const noexcept { + return alias; } private: - id_type seq_value; - id_type hash_value; - std::string_view name_value; + id_type seq; + id_type identifier; + std::string_view alias; }; - /** * @brief Compares the contents of two type info objects. * @param lhs A type info object. * @param rhs A type info object. - * @return True if the two contents differ, false otherwise. + * @return True if the two type info objects are identical, false otherwise. */ -[[nodiscard]] inline bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT { +[[nodiscard]] inline constexpr bool operator==(const type_info &lhs, const type_info &rhs) noexcept { + return lhs.hash() == rhs.hash(); +} + +/** + * @brief Compares the contents of two type info objects. + * @param lhs A type info object. + * @param rhs A type info object. + * @return True if the two type info objects differ, false otherwise. + */ +[[nodiscard]] inline constexpr bool operator!=(const type_info &lhs, const type_info &rhs) noexcept { return !(lhs == rhs); } +/** + * @brief Compares two type info objects. + * @param lhs A valid type info object. + * @param rhs A valid type info object. + * @return True if the first element is less than the second, false otherwise. + */ +[[nodiscard]] constexpr bool operator<(const type_info &lhs, const type_info &rhs) noexcept { + return lhs.index() < rhs.index(); +} /** - * @brief Returns the type info object for a given type. + * @brief Compares two type info objects. + * @param lhs A valid type info object. + * @param rhs A valid type info object. + * @return True if the first element is less than or equal to the second, false + * otherwise. + */ +[[nodiscard]] constexpr bool operator<=(const type_info &lhs, const type_info &rhs) noexcept { + return !(rhs < lhs); +} + +/** + * @brief Compares two type info objects. + * @param lhs A valid type info object. + * @param rhs A valid type info object. + * @return True if the first element is greater than the second, false + * otherwise. + */ +[[nodiscard]] constexpr bool operator>(const type_info &lhs, const type_info &rhs) noexcept { + return rhs < lhs; +} + +/** + * @brief Compares two type info objects. + * @param lhs A valid type info object. + * @param rhs A valid type info object. + * @return True if the first element is greater than or equal to the second, + * false otherwise. + */ +[[nodiscard]] constexpr bool operator>=(const type_info &lhs, const type_info &rhs) noexcept { + return !(lhs < rhs); +} + +/** + * @brief Returns the type info object associated to a given type. + * + * The returned element refers to an object with static storage duration.
+ * The type doesn't need to be a complete type. If the type is a reference, the + * result refers to the referenced type. In all cases, top-level cv-qualifiers + * are ignored. + * * @tparam Type Type for which to generate a type info object. - * @return The type info object for the given type. + * @return A reference to a properly initialized type info object. */ template -[[nodiscard]] type_info type_id() ENTT_NOEXCEPT { - return type_info{ - type_seq>>::value(), - type_hash>>::value(), - type_name>>::value() - }; +[[nodiscard]] const type_info &type_id() noexcept { + if constexpr(std::is_same_v>>) { + static type_info instance{std::in_place_type}; + return instance; + } else { + return type_id>>(); + } } - +/*! @copydoc type_id */ +template +[[nodiscard]] const type_info &type_id(Type &&) noexcept { + return type_id>>(); } +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/core/type_traits.hpp b/LiteLoader/third-party/include/entt/core/type_traits.hpp index d98c726..4352e2f 100644 --- a/LiteLoader/third-party/include/entt/core/type_traits.hpp +++ b/LiteLoader/third-party/include/entt/core/type_traits.hpp @@ -1,18 +1,15 @@ #ifndef ENTT_CORE_TYPE_TRAITS_HPP #define ENTT_CORE_TYPE_TRAITS_HPP - #include #include #include #include -#include "third-party/include/entt/config/config.h" +#include "../config/config.h" #include "fwd.hpp" - namespace entt { - /** * @brief Utility class to disambiguate overloaded functions. * @tparam N Number of choices available. @@ -20,17 +17,13 @@ namespace entt { template struct choice_t // Unfortunately, doxygen cannot parse such a construct. - /*! @cond TURN_OFF_DOXYGEN */ - : choice_t - /*! @endcond */ + : /*! @cond TURN_OFF_DOXYGEN */ choice_t /*! @endcond */ {}; - /*! @copybrief choice_t */ template<> struct choice_t<0> {}; - /** * @brief Variable template for the choice trick. * @tparam N Number of choices available. @@ -38,7 +31,6 @@ struct choice_t<0> {}; template inline constexpr choice_t choice{}; - /** * @brief Identity type trait. * @@ -53,7 +45,6 @@ struct type_identity { using type = Type; }; - /** * @brief Helper type. * @tparam Type A type. @@ -61,7 +52,6 @@ struct type_identity { template using type_identity_t = typename type_identity::type; - /** * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains. * @tparam Type The type of which to return the size. @@ -70,30 +60,25 @@ using type_identity_t = typename type_identity::type; template struct size_of: std::integral_constant {}; - /*! @copydoc size_of */ template struct size_of> - : std::integral_constant -{}; - + : std::integral_constant {}; /** * @brief Helper variable template. * @tparam Type The type of which to return the size. */ -template +template inline constexpr std::size_t size_of_v = size_of::value; - /** * @brief Using declaration to be used to _repeat_ the same type a number of * times equal to the size of a given parameter pack. * @tparam Type A type to repeat. */ template -using unpack_as_t = Type; - +using unpack_as_type = Type; /** * @brief Helper variable template to be used to _repeat_ the same value a @@ -101,8 +86,7 @@ using unpack_as_t = Type; * @tparam Value A value to repeat. */ template -inline constexpr auto unpack_as_v = Value; - +inline constexpr auto unpack_as_value = Value; /** * @brief Wraps a static constant. @@ -111,7 +95,6 @@ inline constexpr auto unpack_as_v = Value; template using integral_constant = std::integral_constant; - /** * @brief Alias template to facilitate the creation of named values. * @tparam Value A constant value at least convertible to `id_type`. @@ -119,7 +102,6 @@ using integral_constant = std::integral_constant; template using tag = integral_constant; - /** * @brief A class to use to push around lists of types, nothing more. * @tparam Type Types provided by the type list. @@ -132,36 +114,31 @@ struct type_list { static constexpr auto size = sizeof...(Type); }; - /*! @brief Primary template isn't defined on purpose. */ template struct type_list_element; - /** * @brief Provides compile-time indexed access to the types of a type list. * @tparam Index Index of the type to return. - * @tparam Type First type provided by the type list. + * @tparam First First type provided by the type list. * @tparam Other Other types provided by the type list. */ -template -struct type_list_element> - : type_list_element> -{}; - +template +struct type_list_element> + : type_list_element> {}; /** * @brief Provides compile-time indexed access to the types of a type list. - * @tparam Type First type provided by the type list. + * @tparam First First type provided by the type list. * @tparam Other Other types provided by the type list. */ -template -struct type_list_element<0u, type_list> { +template +struct type_list_element<0u, type_list> { /*! @brief Searched type. */ - using type = Type; + using type = First; }; - /** * @brief Helper type. * @tparam Index Index of the type to return. @@ -170,6 +147,57 @@ struct type_list_element<0u, type_list> { template using type_list_element_t = typename type_list_element::type; +/*! @brief Primary template isn't defined on purpose. */ +template +struct type_list_index; + +/** + * @brief Provides compile-time type access to the types of a type list. + * @tparam Type Type to look for and for which to return the index. + * @tparam First First type provided by the type list. + * @tparam Other Other types provided by the type list. + */ +template +struct type_list_index> { + /*! @brief Unsigned integer type. */ + using value_type = std::size_t; + /*! @brief Compile-time position of the given type in the sublist. */ + static constexpr value_type value = 1u + type_list_index>::value; +}; + +/** + * @brief Provides compile-time type access to the types of a type list. + * @tparam Type Type to look for and for which to return the index. + * @tparam Other Other types provided by the type list. + */ +template +struct type_list_index> { + static_assert(type_list_index>::value == sizeof...(Other), "Non-unique type"); + /*! @brief Unsigned integer type. */ + using value_type = std::size_t; + /*! @brief Compile-time position of the given type in the sublist. */ + static constexpr value_type value = 0u; +}; + +/** + * @brief Provides compile-time type access to the types of a type list. + * @tparam Type Type to look for and for which to return the index. + */ +template +struct type_list_index> { + /*! @brief Unsigned integer type. */ + using value_type = std::size_t; + /*! @brief Compile-time position of the given type in the sublist. */ + static constexpr value_type value = 0u; +}; + +/** + * @brief Helper variable template. + * @tparam List Type list. + * @tparam Type Type to look for and for which to return the index. + */ +template +inline constexpr std::size_t type_list_index_v = type_list_index::value; /** * @brief Concatenates multiple type lists. @@ -178,14 +206,14 @@ using type_list_element_t = typename type_list_element::type; * @return A type list composed by the types of both the type lists. */ template -constexpr type_list operator+(type_list, type_list) { return {}; } - +constexpr type_list operator+(type_list, type_list) { + return {}; +} /*! @brief Primary template isn't defined on purpose. */ template struct type_list_cat; - /*! @brief Concatenates multiple type lists. */ template<> struct type_list_cat<> { @@ -193,7 +221,6 @@ struct type_list_cat<> { using type = type_list<>; }; - /** * @brief Concatenates multiple type lists. * @tparam Type Types provided by the first type list. @@ -206,7 +233,6 @@ struct type_list_cat, type_list, List...> { using type = typename type_list_cat, List...>::type; }; - /** * @brief Concatenates multiple type lists. * @tparam Type Types provided by the type list. @@ -217,7 +243,6 @@ struct type_list_cat> { using type = type_list; }; - /** * @brief Helper type. * @tparam List Type lists to concatenate. @@ -225,12 +250,10 @@ struct type_list_cat> { template using type_list_cat_t = typename type_list_cat::type; - /*! @brief Primary template isn't defined on purpose. */ template struct type_list_unique; - /** * @brief Removes duplicates types from a type list. * @tparam Type One of the types provided by the given type list. @@ -240,13 +263,11 @@ template struct type_list_unique> { /*! @brief A type list without duplicate types. */ using type = std::conditional_t< - std::disjunction_v...>, + (std::is_same_v || ...), typename type_list_unique>::type, - type_list_cat_t, typename type_list_unique>::type> - >; + type_list_cat_t, typename type_list_unique>::type>>; }; - /*! @brief Removes duplicates types from a type list. */ template<> struct type_list_unique> { @@ -254,7 +275,6 @@ struct type_list_unique> { using type = type_list<>; }; - /** * @brief Helper type. * @tparam Type A type list. @@ -262,7 +282,6 @@ struct type_list_unique> { template using type_list_unique_t = typename type_list_unique::type; - /** * @brief Provides the member constant `value` to true if a type list contains a * given type, false otherwise. @@ -272,7 +291,6 @@ using type_list_unique_t = typename type_list_unique::type; template struct type_list_contains; - /** * @copybrief type_list_contains * @tparam Type Types provided by the type list. @@ -281,21 +299,18 @@ struct type_list_contains; template struct type_list_contains, Other>: std::disjunction...> {}; - /** * @brief Helper variable template. * @tparam List Type list. * @tparam Type Type to look for. */ -template +template inline constexpr bool type_list_contains_v = type_list_contains::value; - /*! @brief Primary template isn't defined on purpose. */ template struct type_list_diff; - /** * @brief Computes the difference between two type lists. * @tparam Type Types provided by the first type list. @@ -307,7 +322,6 @@ struct type_list_diff, type_list> { using type = type_list_cat_t, Type>, type_list<>, type_list>...>; }; - /** * @brief Helper type. * @tparam List Type lists between which to compute the difference. @@ -315,6 +329,28 @@ struct type_list_diff, type_list> { template using type_list_diff_t = typename type_list_diff::type; +/*! @brief Primary template isn't defined on purpose. */ +template class> +struct type_list_transform; + +/** + * @brief Applies a given _function_ to a type list and generate a new list. + * @tparam Type Types provided by the type list. + * @tparam Op Unary operation as template class with a type member named `type`. + */ +template class Op> +struct type_list_transform, Op> { + /*! @brief Resulting type list after applying the transform function. */ + using type = type_list::type...>; +}; + +/** + * @brief Helper type. + * @tparam List Type list. + * @tparam Op Unary operation as template class with a type member named `type`. + */ +template class Op> +using type_list_transform_t = typename type_list_transform::type; /** * @brief A class to use to push around lists of constant values, nothing more. @@ -328,12 +364,10 @@ struct value_list { static constexpr auto size = sizeof...(Value); }; - /*! @brief Primary template isn't defined on purpose. */ template struct value_list_element; - /** * @brief Provides compile-time indexed access to the values of a value list. * @tparam Index Index of the value to return. @@ -342,9 +376,7 @@ struct value_list_element; */ template struct value_list_element> - : value_list_element> -{}; - + : value_list_element> {}; /** * @brief Provides compile-time indexed access to the types of a type list. @@ -357,7 +389,6 @@ struct value_list_element<0u, value_list> { static constexpr auto value = Value; }; - /** * @brief Helper type. * @tparam Index Index of the value to return. @@ -366,7 +397,6 @@ struct value_list_element<0u, value_list> { template inline constexpr auto value_list_element_v = value_list_element::value; - /** * @brief Concatenates multiple value lists. * @tparam Value Values provided by the first value list. @@ -374,14 +404,14 @@ inline constexpr auto value_list_element_v = value_list_element::va * @return A value list composed by the values of both the value lists. */ template -constexpr value_list operator+(value_list, value_list) { return {}; } - +constexpr value_list operator+(value_list, value_list) { + return {}; +} /*! @brief Primary template isn't defined on purpose. */ template struct value_list_cat; - /*! @brief Concatenates multiple value lists. */ template<> struct value_list_cat<> { @@ -389,7 +419,6 @@ struct value_list_cat<> { using type = value_list<>; }; - /** * @brief Concatenates multiple value lists. * @tparam Value Values provided by the first value list. @@ -402,7 +431,6 @@ struct value_list_cat, value_list, List...> { using type = typename value_list_cat, List...>::type; }; - /** * @brief Concatenates multiple value lists. * @tparam Value Values provided by the value list. @@ -413,7 +441,6 @@ struct value_list_cat> { using type = value_list; }; - /** * @brief Helper type. * @tparam List Value lists to concatenate. @@ -421,12 +448,10 @@ struct value_list_cat> { template using value_list_cat_t = typename value_list_cat::type; - /*! @brief Same as std::is_invocable, but with tuples. */ template struct is_applicable: std::false_type {}; - /** * @copybrief is_applicable * @tparam Func A valid function type. @@ -436,7 +461,6 @@ struct is_applicable: std::false_type {}; template class Tuple, typename... Args> struct is_applicable>: std::is_invocable {}; - /** * @copybrief is_applicable * @tparam Func A valid function type. @@ -446,7 +470,6 @@ struct is_applicable>: std::is_invocable {}; template class Tuple, typename... Args> struct is_applicable>: std::is_invocable {}; - /** * @brief Helper variable template. * @tparam Func A valid function type. @@ -455,12 +478,10 @@ struct is_applicable>: std::is_invocable inline constexpr bool is_applicable_v = is_applicable::value; - /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */ template struct is_applicable_r: std::false_type {}; - /** * @copybrief is_applicable_r * @tparam Ret The type to which the return type of the function should be @@ -471,7 +492,6 @@ struct is_applicable_r: std::false_type {}; template struct is_applicable_r>: std::is_invocable_r {}; - /** * @brief Helper variable template. * @tparam Ret The type to which the return type of the function should be @@ -482,7 +502,6 @@ struct is_applicable_r>: std::is_invocable_r inline constexpr bool is_applicable_r_v = is_applicable_r::value; - /** * @brief Provides the member constant `value` to true if a given type is * complete, false otherwise. @@ -491,12 +510,10 @@ inline constexpr bool is_applicable_r_v = is_applicable_r::valu template struct is_complete: std::false_type {}; - /*! @copydoc is_complete */ template struct is_complete>: std::true_type {}; - /** * @brief Helper variable template. * @tparam Type The type to test. @@ -504,7 +521,6 @@ struct is_complete>: std::true_type {} template inline constexpr bool is_complete_v = is_complete::value; - /** * @brief Provides the member constant `value` to true if a given type is an * iterator, false otherwise. @@ -513,13 +529,30 @@ inline constexpr bool is_complete_v = is_complete::value; template struct is_iterator: std::false_type {}; +/** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + +namespace internal { + +template +struct has_iterator_category: std::false_type {}; + +template +struct has_iterator_category::iterator_category>>: std::true_type {}; + +} // namespace internal + +/** + * Internal details not to be documented. + * @endcond + */ /*! @copydoc is_iterator */ template -struct is_iterator::iterator_category>> - : std::true_type -{}; - +struct is_iterator>, void>>> + : internal::has_iterator_category {}; /** * @brief Helper variable template. @@ -528,86 +561,40 @@ struct is_iterator::iterat template inline constexpr bool is_iterator_v = is_iterator::value; - /** - * @brief Provides the member constant `value` to true if a given type is of the - * required iterator type, false otherwise. - * @tparam Type The type to test. - * @tparam It Required iterator type. + * @brief Provides the member constant `value` to true if a given type is both + * an empty and non-final class, false otherwise. + * @tparam Type The type to test */ -template -struct is_iterator_type: std::false_type {}; - - -/*! @copydoc is_iterator_type */ -template -struct is_iterator_type && std::is_same_v>> - : std::true_type -{}; - - -/*! @copydoc is_iterator_type */ -template -struct is_iterator_type, std::void_t>> - : is_iterator_type -{}; - +template +struct is_ebco_eligible + : std::conjunction, std::negation>> {}; /** * @brief Helper variable template. * @tparam Type The type to test. - * @tparam It Required iterator type. */ -template -inline constexpr bool is_iterator_type_v = is_iterator_type::value; - +template +inline constexpr bool is_ebco_eligible_v = is_ebco_eligible::value; /** - * @cond TURN_OFF_DOXYGEN - * Internal details not to be documented. + * @brief Provides the member constant `value` to true if `Type::is_transparent` + * is valid and denotes a type, false otherwise. + * @tparam Type The type to test. */ +template +struct is_transparent: std::false_type {}; - -namespace internal { - - -template -[[nodiscard]] constexpr bool is_equality_comparable(...) { return false; } - - +/*! @copydoc is_transparent */ template -[[nodiscard]] constexpr auto is_equality_comparable(choice_t<0>) --> decltype(std::declval() == std::declval()) { return true; } - - -template -[[nodiscard]] constexpr auto is_equality_comparable(choice_t<1>) --> decltype(std::declval(), std::declval() == std::declval()) { - if constexpr(is_iterator_v) { - return true; - } else if constexpr(std::is_same_v) { - return is_equality_comparable(choice<0>); - } else { - return is_equality_comparable(choice<2>); - } -} - - -template -[[nodiscard]] constexpr auto is_equality_comparable(choice_t<2>) --> decltype(std::declval(), std::declval() == std::declval()) { - return is_equality_comparable(choice<2>) && is_equality_comparable(choice<2>); -} - - -} - +struct is_transparent>: std::true_type {}; /** - * Internal details not to be documented. - * @endcond + * @brief Helper variable template. + * @tparam Type The type to test. */ - +template +inline constexpr bool is_transparent_v = is_transparent::value; /** * @brief Provides the member constant `value` to true if a given type is @@ -615,17 +602,70 @@ template * @tparam Type The type to test. */ template -struct is_equality_comparable: std::bool_constant(choice<2>)> {}; +struct is_equality_comparable: std::false_type {}; +/** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + +namespace internal { + +template +struct has_tuple_size_value: std::false_type {}; + +template +struct has_tuple_size_value::value)>>: std::true_type {}; + +template +[[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence) { + return (is_equality_comparable>::value && ...); +} + +template +[[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) { + return true; +} + +template +[[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval(), bool{}) { + if constexpr(is_iterator_v) { + return true; + } else if constexpr(std::is_same_v) { + return maybe_equality_comparable(choice<0>); + } else { + return is_equality_comparable::value; + } +} + +template +[[nodiscard]] constexpr std::enable_if_t>>, bool> maybe_equality_comparable(choice_t<2>) { + if constexpr(has_tuple_size_value::value) { + return unpack_maybe_equality_comparable(std::make_index_sequence::value>{}); + } else { + return maybe_equality_comparable(choice<1>); + } +} + +} // namespace internal + +/** + * Internal details not to be documented. + * @endcond + */ + +/*! @copydoc is_equality_comparable */ +template +struct is_equality_comparable() == std::declval())>> + : std::bool_constant(choice<2>)> {}; /** * @brief Helper variable template. * @tparam Type The type to test. */ -template +template inline constexpr bool is_equality_comparable_v = is_equality_comparable::value; - /** * @brief Transcribes the constness of a type to another type. * @tparam To The type to which to transcribe the constness. @@ -637,15 +677,13 @@ struct constness_as { using type = std::remove_const_t; }; - /*! @copydoc constness_as */ template struct constness_as { /*! @brief The type resulting from the transcription of the constness. */ - using type = std::add_const_t; + using type = const To; }; - /** * @brief Alias template to facilitate the transcription of the constness. * @tparam To The type to which to transcribe the constness. @@ -654,7 +692,6 @@ struct constness_as { template using constness_as_t = typename constness_as::type; - /** * @brief Extracts the class of a non-static member object or function. * @tparam Member A pointer to a non-static member object or function. @@ -664,20 +701,19 @@ class member_class { static_assert(std::is_member_pointer_v, "Invalid pointer type to non-static member object or function"); template - static Class * clazz(Ret(Class:: *)(Args...)); + static Class *clazz(Ret (Class::*)(Args...)); template - static Class * clazz(Ret(Class:: *)(Args...) const); + static Class *clazz(Ret (Class::*)(Args...) const); template - static Class * clazz(Type Class:: *); + static Class *clazz(Type Class::*); public: /*! @brief The class of the given non-static member object or function. */ using type = std::remove_pointer_t()))>; }; - /** * @brief Helper type. * @tparam Member A pointer to a non-static member object or function. @@ -685,8 +721,38 @@ public: template using member_class_t = typename member_class::type; +/** + * @brief Extracts the n-th argument of a given function or member function. + * @tparam Index The index of the argument to extract. + * @tparam Candidate A valid function, member function or data member. + */ +template +class nth_argument { + template + static constexpr type_list pick_up(Ret (*)(Args...)); -} + template + static constexpr type_list pick_up(Ret (Class ::*)(Args...)); + template + static constexpr type_list pick_up(Ret (Class ::*)(Args...) const); + + template + static constexpr type_list pick_up(Type Class ::*); + +public: + /*! @brief N-th argument of the given function or member function. */ + using type = type_list_element_t; +}; + +/** + * @brief Helper type. + * @tparam Index The index of the argument to extract. + * @tparam Candidate A valid function, member function or data member. + */ +template +using nth_argument_t = typename nth_argument::type; + +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/core/utility.hpp b/LiteLoader/third-party/include/entt/core/utility.hpp index 4621f32..e38f689 100644 --- a/LiteLoader/third-party/include/entt/core/utility.hpp +++ b/LiteLoader/third-party/include/entt/core/utility.hpp @@ -1,16 +1,16 @@ #ifndef ENTT_CORE_UTILITY_HPP #define ENTT_CORE_UTILITY_HPP - +#include #include -#include "third-party/include/entt/config/config.h" - namespace entt { - /*! @brief Identity function object (waiting for C++20). */ struct identity { + /*! @brief Indicates that this is a transparent function object. */ + using is_transparent = void; + /** * @brief Returns its argument unchanged. * @tparam Type Type of the argument. @@ -18,12 +18,11 @@ struct identity { * @return The submitted value as-is. */ template - [[nodiscard]] constexpr Type && operator()(Type &&value) const ENTT_NOEXCEPT { + [[nodiscard]] constexpr Type &&operator()(Type &&value) const noexcept { return std::forward(value); } }; - /** * @brief Constant utility to disambiguate overloaded members of a class. * @tparam Type Type of the desired overload. @@ -32,8 +31,9 @@ struct identity { * @return Pointer to the member. */ template -[[nodiscard]] constexpr auto overload(Type Class:: *member) ENTT_NOEXCEPT { return member; } - +[[nodiscard]] constexpr auto overload(Type Class::*member) noexcept { + return member; +} /** * @brief Constant utility to disambiguate overloaded functions. @@ -42,8 +42,9 @@ template * @return Pointer to the function. */ template -[[nodiscard]] constexpr auto overload(Func *func) ENTT_NOEXCEPT { return func; } - +[[nodiscard]] constexpr auto overload(Func *func) noexcept { + return func; +} /** * @brief Helper type for visitors. @@ -54,15 +55,12 @@ struct overloaded: Func... { using Func::operator()...; }; - /** * @brief Deduction guide. * @tparam Func Types of function objects. */ template -overloaded(Func...) --> overloaded; - +overloaded(Func...) -> overloaded; /** * @brief Basic implementation of a y-combinator. @@ -74,9 +72,8 @@ struct y_combinator { * @brief Constructs a y-combinator from a given function. * @param recursive A potentially recursive function. */ - y_combinator(Func recursive): - func{std::move(recursive)} - {} + constexpr y_combinator(Func recursive) noexcept(std::is_nothrow_move_constructible_v) + : func{std::move(recursive)} {} /** * @brief Invokes a y-combinator and therefore its underlying function. @@ -84,14 +81,14 @@ struct y_combinator { * @param args Parameters to use to invoke the underlying function. * @return Return value of the underlying function, if any. */ - template - decltype(auto) operator()(Args &&... args) const { + template + constexpr decltype(auto) operator()(Args &&...args) const noexcept(std::is_nothrow_invocable_v) { return func(*this, std::forward(args)...); } /*! @copydoc operator()() */ - template - decltype(auto) operator()(Args &&... args) { + template + constexpr decltype(auto) operator()(Args &&...args) noexcept(std::is_nothrow_invocable_v) { return func(*this, std::forward(args)...); } @@ -99,8 +96,6 @@ private: Func func; }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/entity/component.hpp b/LiteLoader/third-party/include/entt/entity/component.hpp index 9865887..07fc9f4 100644 --- a/LiteLoader/third-party/include/entt/entity/component.hpp +++ b/LiteLoader/third-party/include/entt/entity/component.hpp @@ -1,34 +1,64 @@ #ifndef ENTT_ENTITY_COMPONENT_HPP #define ENTT_ENTITY_COMPONENT_HPP - +#include #include -#include "third-party/include/entt/config/config.h" - +#include "../config/config.h" namespace entt { +/** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ -/*! @brief Commonly used default traits for all types. */ -struct basic_component_traits { - /*! @brief Pointer stability, default is `std::false_type`. */ - using in_place_delete = std::false_type; - /*! @brief Empty type optimization, default is `ENTT_IGNORE_IF_EMPTY`. */ - using ignore_if_empty = ENTT_IGNORE_IF_EMPTY; -}; +namespace internal { +template +struct in_place_delete: std::bool_constant && std::is_move_assignable_v)> {}; + +template +struct in_place_delete> + : std::true_type {}; + +template +struct page_size: std::integral_constant * ENTT_PACKED_PAGE> {}; + +template +struct page_size>> + : std::integral_constant {}; + +} // namespace internal + +/** + * Internal details not to be documented. + * @endcond + */ /** * @brief Common way to access various properties of components. * @tparam Type Type of component. */ template -struct component_traits: basic_component_traits { +struct component_traits { static_assert(std::is_same_v, Type>, "Unsupported type"); + + /*! @brief Component type. */ + using type = Type; + + /*! @brief Pointer stability, default is `false`. */ + static constexpr bool in_place_delete = internal::in_place_delete::value; + /*! @brief Page size, default is `ENTT_PACKED_PAGE` for non-empty types. */ + static constexpr std::size_t page_size = internal::page_size::value; }; +/** + * @brief Helper variable template. + * @tparam Type Type of component. + */ +template +inline constexpr bool ignore_as_empty_v = (std::is_void_v || component_traits::page_size == 0u); -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/entity/entity.hpp b/LiteLoader/third-party/include/entt/entity/entity.hpp index 2858f5c..fd7c96b 100644 --- a/LiteLoader/third-party/include/entt/entity/entity.hpp +++ b/LiteLoader/third-party/include/entt/entity/entity.hpp @@ -1,98 +1,85 @@ #ifndef ENTT_ENTITY_ENTITY_HPP #define ENTT_ENTITY_ENTITY_HPP - #include #include #include -#include "third-party/include/entt/config/config.h" - +#include "../config/config.h" +#include "fwd.hpp" namespace entt { - /** * @cond TURN_OFF_DOXYGEN * Internal details not to be documented. */ - namespace internal { - template struct entt_traits; - template struct entt_traits>> - : entt_traits> -{}; - + : entt_traits> {}; template struct entt_traits>> - : entt_traits -{}; - + : entt_traits {}; template<> struct entt_traits { using entity_type = std::uint32_t; using version_type = std::uint16_t; - using difference_type = std::int64_t; static constexpr entity_type entity_mask = 0xFFFFF; static constexpr entity_type version_mask = 0xFFF; static constexpr std::size_t entity_shift = 20u; }; - template<> struct entt_traits { using entity_type = std::uint64_t; using version_type = std::uint32_t; - using difference_type = std::int64_t; static constexpr entity_type entity_mask = 0xFFFFFFFF; static constexpr entity_type version_mask = 0xFFFFFFFF; static constexpr std::size_t entity_shift = 32u; }; - -} - +} // namespace internal /** * Internal details not to be documented. * @endcond */ - /** * @brief Entity traits. * @tparam Type Type of identifier. */ template -class entt_traits: private internal::entt_traits { - using traits_type = internal::entt_traits; +class entt_traits: internal::entt_traits { + using base_type = internal::entt_traits; public: /*! @brief Value type. */ using value_type = Type; /*! @brief Underlying entity type. */ - using entity_type = typename traits_type::entity_type; + using entity_type = typename base_type::entity_type; /*! @brief Underlying version type. */ - using version_type = typename traits_type::version_type; - /*! @brief Difference type. */ - using difference_type = typename traits_type::difference_type; + using version_type = typename base_type::version_type; + /*! @brief Reserved identifier. */ + static constexpr entity_type reserved = base_type::entity_mask | (base_type::version_mask << base_type::entity_shift); + /*! @brief Page size, default is `ENTT_SPARSE_PAGE`. */ + static constexpr auto page_size = ENTT_SPARSE_PAGE; /** * @brief Converts an entity to its underlying type. * @param value The value to convert. * @return The integral representation of the given value. */ - [[nodiscard]] static constexpr entity_type to_integral(const value_type value) ENTT_NOEXCEPT { + [[nodiscard]] static constexpr entity_type to_integral(const value_type value) noexcept { return static_cast(value); } @@ -101,8 +88,8 @@ public: * @param value The value to convert. * @return The integral representation of the entity part. */ - [[nodiscard]] static constexpr entity_type to_entity(const value_type value) ENTT_NOEXCEPT { - return (to_integral(value) & traits_type::entity_mask); + [[nodiscard]] static constexpr entity_type to_entity(const value_type value) noexcept { + return (to_integral(value) & base_type::entity_mask); } /** @@ -110,9 +97,8 @@ public: * @param value The value to convert. * @return The integral representation of the version part. */ - [[nodiscard]] static constexpr version_type to_version(const value_type value) ENTT_NOEXCEPT { - constexpr auto mask = (traits_type::version_mask << traits_type::entity_shift); - return ((to_integral(value) & mask) >> traits_type::entity_shift); + [[nodiscard]] static constexpr version_type to_version(const value_type value) noexcept { + return (to_integral(value) >> base_type::entity_shift); } /** @@ -125,34 +111,64 @@ public: * @param version The version part of the identifier. * @return A properly constructed identifier. */ - [[nodiscard]] static constexpr value_type construct(const entity_type entity = traits_type::entity_mask, const version_type version = traits_type::version_mask) ENTT_NOEXCEPT { - return value_type{(entity & traits_type::entity_mask) | (static_cast(version) << traits_type::entity_shift)}; + [[nodiscard]] static constexpr value_type construct(const entity_type entity, const version_type version) noexcept { + return value_type{(entity & base_type::entity_mask) | (static_cast(version) << base_type::entity_shift)}; + } + + /** + * @brief Combines two identifiers in a single one. + * + * The returned identifier is a copy of the first element except for its + * version, which is taken from the second element. + * + * @param lhs The identifier from which to take the entity part. + * @param rhs The identifier from which to take the version part. + * @return A properly constructed identifier. + */ + [[nodiscard]] static constexpr value_type combine(const entity_type lhs, const entity_type rhs) noexcept { + constexpr auto mask = (base_type::version_mask << base_type::entity_shift); + return value_type{(lhs & base_type::entity_mask) | (rhs & mask)}; } }; - /** - * @brief Converts an entity to its underlying type. + * @copydoc entt_traits::to_integral * @tparam Entity The value type. - * @param entity The value to convert. - * @return The integral representation of the given value. */ template -[[nodiscard]] constexpr auto to_integral(const Entity entity) ENTT_NOEXCEPT { - return entt_traits::to_integral(entity); +[[nodiscard]] constexpr typename entt_traits::entity_type to_integral(const Entity value) noexcept { + return entt_traits::to_integral(value); } +/** + * @copydoc entt_traits::to_entity + * @tparam Entity The value type. + */ +template +[[nodiscard]] constexpr typename entt_traits::entity_type to_entity(const Entity value) noexcept { + return entt_traits::to_entity(value); +} -/*! @brief Null object for all entity identifiers. */ +/** + * @copydoc entt_traits::to_version + * @tparam Entity The value type. + */ +template +[[nodiscard]] constexpr typename entt_traits::version_type to_version(const Entity value) noexcept { + return entt_traits::to_version(value); +} + +/*! @brief Null object for all identifiers. */ struct null_t { /** * @brief Converts the null object to identifiers of any type. - * @tparam Entity Type of entity identifier. + * @tparam Entity Type of identifier. * @return The null representation for the given type. */ template - [[nodiscard]] constexpr operator Entity() const ENTT_NOEXCEPT { - return entt_traits::construct(); + [[nodiscard]] constexpr operator Entity() const noexcept { + using entity_traits = entt_traits; + return entity_traits::combine(entity_traits::reserved, entity_traits::reserved); } /** @@ -160,7 +176,7 @@ struct null_t { * @param other A null object. * @return True in all cases. */ - [[nodiscard]] constexpr bool operator==([[maybe_unused]] const null_t other) const ENTT_NOEXCEPT { + [[nodiscard]] constexpr bool operator==([[maybe_unused]] const null_t other) const noexcept { return true; } @@ -169,81 +185,69 @@ struct null_t { * @param other A null object. * @return False in all cases. */ - [[nodiscard]] constexpr bool operator!=([[maybe_unused]] const null_t other) const ENTT_NOEXCEPT { + [[nodiscard]] constexpr bool operator!=([[maybe_unused]] const null_t other) const noexcept { return false; } /** - * @brief Compares a null object and an entity identifier of any type. - * @tparam Entity Type of entity identifier. - * @param entity Entity identifier with which to compare. + * @brief Compares a null object and an identifier of any type. + * @tparam Entity Type of identifier. + * @param entity Identifier with which to compare. * @return False if the two elements differ, true otherwise. */ template - [[nodiscard]] constexpr bool operator==(const Entity entity) const ENTT_NOEXCEPT { - return entt_traits::to_entity(entity) == entt_traits::to_entity(*this); + [[nodiscard]] constexpr bool operator==(const Entity entity) const noexcept { + using entity_traits = entt_traits; + return entity_traits::to_entity(entity) == entity_traits::to_entity(*this); } /** - * @brief Compares a null object and an entity identifier of any type. - * @tparam Entity Type of entity identifier. - * @param entity Entity identifier with which to compare. + * @brief Compares a null object and an identifier of any type. + * @tparam Entity Type of identifier. + * @param entity Identifier with which to compare. * @return True if the two elements differ, false otherwise. */ template - [[nodiscard]] constexpr bool operator!=(const Entity entity) const ENTT_NOEXCEPT { + [[nodiscard]] constexpr bool operator!=(const Entity entity) const noexcept { return !(entity == *this); } - - /** - * @brief Creates a null object from an entity identifier of any type. - * @tparam Entity Type of entity identifier. - * @param entity Entity identifier to turn into a null object. - * @return The null representation for the given identifier. - */ - template - [[nodiscard]] constexpr Entity operator|(const Entity entity) const ENTT_NOEXCEPT { - return entt_traits::construct(entt_traits::to_entity(*this), entt_traits::to_version(entity)); - } }; - /** - * @brief Compares a null object and an entity identifier of any type. - * @tparam Entity Type of entity identifier. - * @param entity Entity identifier with which to compare. + * @brief Compares a null object and an identifier of any type. + * @tparam Entity Type of identifier. + * @param entity Identifier with which to compare. * @param other A null object yet to be converted. * @return False if the two elements differ, true otherwise. */ template -[[nodiscard]] constexpr bool operator==(const Entity entity, const null_t other) ENTT_NOEXCEPT { +[[nodiscard]] constexpr bool operator==(const Entity entity, const null_t other) noexcept { return other.operator==(entity); } - /** - * @brief Compares a null object and an entity identifier of any type. - * @tparam Entity Type of entity identifier. - * @param entity Entity identifier with which to compare. + * @brief Compares a null object and an identifier of any type. + * @tparam Entity Type of identifier. + * @param entity Identifier with which to compare. * @param other A null object yet to be converted. * @return True if the two elements differ, false otherwise. */ template -[[nodiscard]] constexpr bool operator!=(const Entity entity, const null_t other) ENTT_NOEXCEPT { +[[nodiscard]] constexpr bool operator!=(const Entity entity, const null_t other) noexcept { return !(other == entity); } - -/*! @brief Tombstone object for all entity identifiers. */ +/*! @brief Tombstone object for all identifiers. */ struct tombstone_t { /** * @brief Converts the tombstone object to identifiers of any type. - * @tparam Entity Type of entity identifier. + * @tparam Entity Type of identifier. * @return The tombstone representation for the given type. */ template - [[nodiscard]] constexpr operator Entity() const ENTT_NOEXCEPT { - return entt_traits::construct(); + [[nodiscard]] constexpr operator Entity() const noexcept { + using entity_traits = entt_traits; + return entity_traits::combine(entity_traits::reserved, entity_traits::reserved); } /** @@ -251,7 +255,7 @@ struct tombstone_t { * @param other A tombstone object. * @return True in all cases. */ - [[nodiscard]] constexpr bool operator==([[maybe_unused]] const tombstone_t other) const ENTT_NOEXCEPT { + [[nodiscard]] constexpr bool operator==([[maybe_unused]] const tombstone_t other) const noexcept { return true; } @@ -260,92 +264,76 @@ struct tombstone_t { * @param other A tombstone object. * @return False in all cases. */ - [[nodiscard]] constexpr bool operator!=([[maybe_unused]] const tombstone_t other) const ENTT_NOEXCEPT { + [[nodiscard]] constexpr bool operator!=([[maybe_unused]] const tombstone_t other) const noexcept { return false; } /** - * @brief Compares a tombstone object and an entity identifier of any type. - * @tparam Entity Type of entity identifier. - * @param entity Entity identifier with which to compare. + * @brief Compares a tombstone object and an identifier of any type. + * @tparam Entity Type of identifier. + * @param entity Identifier with which to compare. * @return False if the two elements differ, true otherwise. */ template - [[nodiscard]] constexpr bool operator==(const Entity entity) const ENTT_NOEXCEPT { - return entt_traits::to_version(entity) == entt_traits::to_version(*this); + [[nodiscard]] constexpr bool operator==(const Entity entity) const noexcept { + using entity_traits = entt_traits; + return entity_traits::to_version(entity) == entity_traits::to_version(*this); } /** - * @brief Compares a tombstone object and an entity identifier of any type. - * @tparam Entity Type of entity identifier. - * @param entity Entity identifier with which to compare. + * @brief Compares a tombstone object and an identifier of any type. + * @tparam Entity Type of identifier. + * @param entity Identifier with which to compare. * @return True if the two elements differ, false otherwise. */ template - [[nodiscard]] constexpr bool operator!=(const Entity entity) const ENTT_NOEXCEPT { + [[nodiscard]] constexpr bool operator!=(const Entity entity) const noexcept { return !(entity == *this); } - - /** - * @brief Creates a tombstone object from an entity identifier of any type. - * @tparam Entity Type of entity identifier. - * @param entity Entity identifier to turn into a tombstone object. - * @return The tombstone representation for the given identifier. - */ - template - [[nodiscard]] constexpr Entity operator|(const Entity entity) const ENTT_NOEXCEPT { - return entt_traits::construct(entt_traits::to_entity(entity)); - } }; - /** - * @brief Compares a tombstone object and an entity identifier of any type. - * @tparam Entity Type of entity identifier. - * @param entity Entity identifier with which to compare. + * @brief Compares a tombstone object and an identifier of any type. + * @tparam Entity Type of identifier. + * @param entity Identifier with which to compare. * @param other A tombstone object yet to be converted. * @return False if the two elements differ, true otherwise. */ template -[[nodiscard]] constexpr bool operator==(const Entity entity, const tombstone_t other) ENTT_NOEXCEPT { +[[nodiscard]] constexpr bool operator==(const Entity entity, const tombstone_t other) noexcept { return other.operator==(entity); } - /** - * @brief Compares a tombstone object and an entity identifier of any type. - * @tparam Entity Type of entity identifier. - * @param entity Entity identifier with which to compare. + * @brief Compares a tombstone object and an identifier of any type. + * @tparam Entity Type of identifier. + * @param entity Identifier with which to compare. * @param other A tombstone object yet to be converted. * @return True if the two elements differ, false otherwise. */ template -[[nodiscard]] constexpr bool operator!=(const Entity entity, const tombstone_t other) ENTT_NOEXCEPT { +[[nodiscard]] constexpr bool operator!=(const Entity entity, const tombstone_t other) noexcept { return !(other == entity); } - /** * @brief Compile-time constant for null entities. * - * There exist implicit conversions from this variable to entity identifiers of - * any allowed type. Similarly, there exist comparision operators between the - * null entity and any other entity identifier. + * There exist implicit conversions from this variable to identifiers of any + * allowed type. Similarly, there exist comparison operators between the null + * entity and any other identifier. */ inline constexpr null_t null{}; - /** * @brief Compile-time constant for tombstone entities. * - * There exist implicit conversions from this variable to entity identifiers of - * any allowed type. Similarly, there exist comparision operators between the - * tombstone entity and any other entity identifier. + * There exist implicit conversions from this variable to identifiers of any + * allowed type. Similarly, there exist comparison operators between the + * tombstone entity and any other identifier. */ inline constexpr tombstone_t tombstone{}; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/entity/fwd.hpp b/LiteLoader/third-party/include/entt/entity/fwd.hpp index bc394fe..8cc49aa 100644 --- a/LiteLoader/third-party/include/entt/entity/fwd.hpp +++ b/LiteLoader/third-party/include/entt/entity/fwd.hpp @@ -1,147 +1,174 @@ #ifndef ENTT_ENTITY_FWD_HPP #define ENTT_ENTITY_FWD_HPP - #include -#include "third-party/include/entt/core/fwd.hpp" - +#include +#include "../core/fwd.hpp" +#include "../core/type_traits.hpp" namespace entt { +/*! @brief Default entity identifier. */ +enum class entity : id_type {}; -template> +template> class basic_sparse_set; +template, typename = void> +class basic_storage; -template> -struct basic_storage; +template, typename = void> +struct storage_type; +template>> +struct storage_for; -template +template +class sigh_storage_mixin; + +template> class basic_registry; +template +class basic_view; -template -struct basic_view; - - -template +template> class basic_runtime_view; - -template +template class basic_group; - template class basic_observer; - template class basic_organizer; - template struct basic_handle; - template class basic_snapshot; - template class basic_snapshot_loader; - template class basic_continuous_loader; +/** + * @brief Alias for exclusion lists. + * @tparam Type List of types. + */ +template +using exclude_t = type_list; -/*! @brief Default entity identifier. */ -enum class entity: id_type {}; +/** + * @brief Variable template for exclusion lists. + * @tparam Type List of types. + */ +template +inline constexpr exclude_t exclude{}; +/** + * @brief Alias for lists of observed components. + * @tparam Type List of types. + */ +template +using get_t = type_list; + +/** + * @brief Variable template for lists of observed components. + * @tparam Type List of types. + */ +template +inline constexpr get_t get{}; + +/** + * @brief Alias for lists of owned components. + * @tparam Type List of types. + */ +template +using owned_t = type_list; + +/** + * @brief Variable template for lists of owned components. + * @tparam Type List of types. + */ +template +inline constexpr owned_t owned{}; /*! @brief Alias declaration for the most common use case. */ -using sparse_set = basic_sparse_set; +using sparse_set = basic_sparse_set<>; +/** + * @brief Alias declaration for the most common use case. + * @tparam Type Type of objects assigned to the entities. + */ +template +using storage = basic_storage; + +/*! @brief Alias declaration for the most common use case. */ +using registry = basic_registry<>; + +/*! @brief Alias declaration for the most common use case. */ +using observer = basic_observer; + +/*! @brief Alias declaration for the most common use case. */ +using organizer = basic_organizer; + +/*! @brief Alias declaration for the most common use case. */ +using handle = basic_handle; + +/*! @brief Alias declaration for the most common use case. */ +using const_handle = basic_handle; /** * @brief Alias declaration for the most common use case. * @tparam Args Other template parameters. */ template -using storage = basic_storage; - - -/*! @brief Alias declaration for the most common use case. */ -using registry = basic_registry; - - -/*! @brief Alias declaration for the most common use case. */ -using observer = basic_observer; - - -/*! @brief Alias declaration for the most common use case. */ -using organizer = basic_organizer; - - -/*! @brief Alias declaration for the most common use case. */ -using handle = basic_handle; - - -/*! @brief Alias declaration for the most common use case. */ -using const_handle = basic_handle; - +using handle_view = basic_handle; /** * @brief Alias declaration for the most common use case. * @tparam Args Other template parameters. */ template -using handle_view = basic_handle; +using const_handle_view = basic_handle; +/*! @brief Alias declaration for the most common use case. */ +using snapshot = basic_snapshot; + +/*! @brief Alias declaration for the most common use case. */ +using snapshot_loader = basic_snapshot_loader; + +/*! @brief Alias declaration for the most common use case. */ +using continuous_loader = basic_continuous_loader; /** * @brief Alias declaration for the most common use case. - * @tparam Args Other template parameters. + * @tparam Get Types of storage iterated by the view. + * @tparam Exclude Types of storage used to filter the view. */ -template -using const_handle_view = basic_handle; - +template> +using view = basic_view, type_list_transform_t>; /*! @brief Alias declaration for the most common use case. */ -using snapshot = basic_snapshot; - +using runtime_view = basic_runtime_view; /*! @brief Alias declaration for the most common use case. */ -using snapshot_loader = basic_snapshot_loader; - - -/*! @brief Alias declaration for the most common use case. */ -using continuous_loader = basic_continuous_loader; - +using const_runtime_view = basic_runtime_view; /** * @brief Alias declaration for the most common use case. - * @tparam Args Other template parameters. + * @tparam Owned Types of storage _owned_ by the group. + * @tparam Get Types of storage _observed_ by the group. + * @tparam Exclude Types of storage used to filter the group. */ -template -using view = basic_view; - - -/*! @brief Alias declaration for the most common use case. */ -using runtime_view = basic_runtime_view; - - -/** - * @brief Alias declaration for the most common use case. - * @tparam Args Other template parameters. - */ -template -using group = basic_group; - - -} +template +using group = basic_group, type_list_transform_t, type_list_transform_t>; +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/entity/group.hpp b/LiteLoader/third-party/include/entt/entity/group.hpp index 38fc5f6..f385986 100644 --- a/LiteLoader/third-party/include/entt/entity/group.hpp +++ b/LiteLoader/third-party/include/entt/entity/group.hpp @@ -1,21 +1,97 @@ #ifndef ENTT_ENTITY_GROUP_HPP #define ENTT_ENTITY_GROUP_HPP - #include -#include #include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/type_traits.hpp" +#include +#include "../config/config.h" +#include "../core/iterator.hpp" +#include "../core/type_traits.hpp" +#include "component.hpp" #include "entity.hpp" #include "fwd.hpp" #include "sparse_set.hpp" #include "storage.hpp" -#include "utility.hpp" - namespace entt { +/** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + +namespace internal { + +template +class extended_group_iterator; + +template +class extended_group_iterator, get_t> { + template + auto index_to_element(Type &cpool) const { + if constexpr(ignore_as_empty_v) { + return std::make_tuple(); + } else { + return std::forward_as_tuple(cpool.rbegin()[it.index()]); + } + } + +public: + using difference_type = std::ptrdiff_t; + using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval()), std::declval().get_as_tuple({})..., std::declval().get_as_tuple({})...)); + using pointer = input_iterator_pointer; + using reference = value_type; + using iterator_category = std::input_iterator_tag; + + constexpr extended_group_iterator() + : it{}, + pools{} {} + + extended_group_iterator(It from, const std::tuple &cpools) + : it{from}, + pools{cpools} {} + + extended_group_iterator &operator++() noexcept { + return ++it, *this; + } + + extended_group_iterator operator++(int) noexcept { + extended_group_iterator orig = *this; + return ++(*this), orig; + } + + [[nodiscard]] reference operator*() const noexcept { + return std::tuple_cat(std::make_tuple(*it), index_to_element(*std::get(pools))..., std::get(pools)->get_as_tuple(*it)...); + } + + [[nodiscard]] pointer operator->() const noexcept { + return operator*(); + } + + template + friend constexpr bool operator==(const extended_group_iterator &, const extended_group_iterator &) noexcept; + +private: + It it; + std::tuple pools; +}; + +template +[[nodiscard]] constexpr bool operator==(const extended_group_iterator &lhs, const extended_group_iterator &rhs) noexcept { + return lhs.it == rhs.it; +} + +template +[[nodiscard]] constexpr bool operator!=(const extended_group_iterator &lhs, const extended_group_iterator &rhs) noexcept { + return !(lhs == rhs); +} + +} // namespace internal + +/** + * Internal details not to be documented. + * @endcond + */ /** * @brief Group. @@ -23,155 +99,99 @@ namespace entt { * Primary template isn't defined on purpose. All the specializations give a * compile-time error, but for a few reasonable cases. */ -template +template class basic_group; - /** * @brief Non-owning group. * - * A non-owning group returns all entities and only the entities that have at - * least the given components. Moreover, it's guaranteed that the entity list - * is tightly packed in memory for fast iterations. + * A non-owning group returns all entities and only the entities that are at + * least in the given storage. Moreover, it's guaranteed that the entity list is + * tightly packed in memory for fast iterations. * * @b Important * * Iterators aren't invalidated if: * - * * New instances of the given components are created and assigned to entities. - * * The entity currently pointed is modified (as an example, if one of the - * given components is removed from the entity to which the iterator points). + * * New elements are added to the storage. + * * The entity currently pointed is modified (for example, components are added + * or removed from it). * * The entity currently pointed is destroyed. * * In all other cases, modifying the pools iterated by the group in any way * invalidates all the iterators and using them results in undefined behavior. * - * @note - * Groups share references to the underlying data structures of the registry - * that generated them. Therefore any change to the entities and to the - * components made by means of the registry are immediately reflected by all the - * groups.
- * Moreover, sorting a non-owning group affects all the instances of the same - * group (it means that users don't have to call `sort` on each instance to sort - * all of them because they _share_ entities and components). - * - * @warning - * Lifetime of a group must not overcome that of the registry that generated it. - * In any other case, attempting to use a group results in undefined behavior. - * - * @tparam Entity A valid entity type (see entt_traits for more details). - * @tparam Exclude Types of components used to filter the group. - * @tparam Get Type of components observed by the group. + * @tparam Get Types of storage _observed_ by the group. + * @tparam Exclude Types of storage used to filter the group. */ -template -class basic_group, get_t> final { - /*! @brief A registry is allowed to create groups. */ - friend class basic_registry; +template +class basic_group, get_t, exclude_t> { + using underlying_type = std::common_type_t; + using basic_common_type = std::common_type_t; - using basic_common_type = basic_sparse_set; - - template - using storage_type = constness_as_t>::storage_type, Component>; - - class iterable final { - template - struct iterable_iterator final { - using difference_type = std::ptrdiff_t; - using value_type = decltype(std::tuple_cat(std::tuple{}, std::declval().get({}))); - using pointer = void; - using reference = value_type; - using iterator_category = std::input_iterator_tag; - - template - iterable_iterator(It from, const std::tuple *...> &args) ENTT_NOEXCEPT - : it{from}, - pools{args} - {} - - iterable_iterator & operator++() ENTT_NOEXCEPT { - return ++it, *this; - } - - iterable_iterator operator++(int) ENTT_NOEXCEPT { - iterable_iterator orig = *this; - return ++(*this), orig; - } - - [[nodiscard]] reference operator*() const ENTT_NOEXCEPT { - const auto entt = *it; - return std::tuple_cat(std::make_tuple(entt), get_as_tuple(*std::get *>(pools), entt)...); - } - - [[nodiscard]] bool operator==(const iterable_iterator &other) const ENTT_NOEXCEPT { - return other.it == it; - } - - [[nodiscard]] bool operator!=(const iterable_iterator &other) const ENTT_NOEXCEPT { - return !(*this == other); - } - - private: - It it; - std::tuple *...> pools; - }; - - public: - using iterator = iterable_iterator; - using reverse_iterator = iterable_iterator; - - iterable(basic_common_type * const ref, const std::tuple *...> &cpools) - : handler{ref}, - pools{cpools} - {} - - [[nodiscard]] iterator begin() const ENTT_NOEXCEPT { - return handler ? iterator{handler->begin(), pools} : iterator{{}, pools}; - } - - [[nodiscard]] iterator end() const ENTT_NOEXCEPT { - return handler ? iterator{handler->end(), pools} : iterator{{}, pools}; - } - - [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT { - return handler ? reverse_iterator{handler->rbegin(), pools} : reverse_iterator{{}, pools}; - } - - [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT { - return handler ? reverse_iterator{handler->rend(), pools} : reverse_iterator{{}, pools}; - } - - private: - basic_common_type * const handler; - const std::tuple *...> pools; - }; - - basic_group(basic_common_type &ref, storage_type &... gpool) ENTT_NOEXCEPT - : handler{&ref}, - pools{&gpool...} - {} + template + static constexpr std::size_t index_of = type_list_index_v, type_list>; public: /*! @brief Underlying entity identifier. */ - using entity_type = Entity; + using entity_type = underlying_type; /*! @brief Unsigned integer type. */ using size_type = std::size_t; + /*! @brief Common type among all storage types. */ + using base_type = basic_common_type; /*! @brief Random access iterator type. */ - using iterator = typename basic_common_type::iterator; + using iterator = typename base_type::iterator; /*! @brief Reversed iterator type. */ - using reverse_iterator = typename basic_common_type::reverse_iterator; + using reverse_iterator = typename base_type::reverse_iterator; /*! @brief Iterable group type. */ - using iterable_group = iterable; + using iterable = iterable_adaptor, get_t>>; /*! @brief Default constructor to use to create empty, invalid groups. */ - basic_group() ENTT_NOEXCEPT - : handler{} - {} + basic_group() noexcept + : handler{} {} /** - * @brief Returns the number of entities that have the given components. - * @return Number of entities that have the given components. + * @brief Constructs a group from a set of storage classes. + * @param ref The actual entities to iterate. + * @param gpool Storage types to iterate _observed_ by the group. */ - [[nodiscard]] size_type size() const ENTT_NOEXCEPT { + basic_group(basic_common_type &ref, Get &...gpool) noexcept + : handler{&ref}, + pools{&gpool...} {} + + /** + * @brief Returns a const reference to the underlying handler. + * @return A const reference to the underlying handler. + */ + [[nodiscard]] const base_type &handle() const noexcept { + return *handler; + } + + /** + * @brief Returns the storage for a given component type. + * @tparam Type Type of component of which to return the storage. + * @return The storage for the given component type. + */ + template + [[nodiscard]] decltype(auto) storage() const noexcept { + return storage>(); + } + + /** + * @brief Returns the storage for a given index. + * @tparam Index Index of the storage to return. + * @return The storage for the given index. + */ + template + [[nodiscard]] decltype(auto) storage() const noexcept { + return *std::get(pools); + } + + /** + * @brief Returns the number of entities that are part of the group. + * @return Number of entities that are part of the group. + */ + [[nodiscard]] size_type size() const noexcept { return *this ? handler->size() : size_type{}; } @@ -180,7 +200,7 @@ public: * allocated space for. * @return Capacity of the group. */ - [[nodiscard]] size_type capacity() const ENTT_NOEXCEPT { + [[nodiscard]] size_type capacity() const noexcept { return *this ? handler->capacity() : size_type{}; } @@ -195,22 +215,10 @@ public: * @brief Checks whether a group is empty. * @return True if the group is empty, false otherwise. */ - [[nodiscard]] bool empty() const ENTT_NOEXCEPT { + [[nodiscard]] bool empty() const noexcept { return !*this || handler->empty(); } - /** - * @brief Direct access to the list of entities. - * - * The returned pointer is such that range `[data(), data() + size())` is - * always a valid range, even if the container is empty. - * - * @return A pointer to the array of entities. - */ - [[nodiscard]] auto data() const ENTT_NOEXCEPT { - return *this ? handler->data() : nullptr; - } - /** * @brief Returns an iterator to the first entity of the group. * @@ -219,7 +227,7 @@ public: * * @return An iterator to the first entity of the group. */ - [[nodiscard]] iterator begin() const ENTT_NOEXCEPT { + [[nodiscard]] iterator begin() const noexcept { return *this ? handler->begin() : iterator{}; } @@ -233,7 +241,7 @@ public: * @return An iterator to the entity following the last entity of the * group. */ - [[nodiscard]] iterator end() const ENTT_NOEXCEPT { + [[nodiscard]] iterator end() const noexcept { return *this ? handler->end() : iterator{}; } @@ -245,7 +253,7 @@ public: * * @return An iterator to the first entity of the reversed group. */ - [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT { + [[nodiscard]] reverse_iterator rbegin() const noexcept { return *this ? handler->rbegin() : reverse_iterator{}; } @@ -260,7 +268,7 @@ public: * @return An iterator to the entity following the last entity of the * reversed group. */ - [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT { + [[nodiscard]] reverse_iterator rend() const noexcept { return *this ? handler->rend() : reverse_iterator{}; } @@ -269,7 +277,7 @@ public: * @return The first entity of the group if one exists, the null entity * otherwise. */ - [[nodiscard]] entity_type front() const { + [[nodiscard]] entity_type front() const noexcept { const auto it = begin(); return it != end() ? *it : null; } @@ -279,18 +287,18 @@ public: * @return The last entity of the group if one exists, the null entity * otherwise. */ - [[nodiscard]] entity_type back() const { + [[nodiscard]] entity_type back() const noexcept { const auto it = rbegin(); return it != rend() ? *it : null; } /** * @brief Finds an entity. - * @param entt A valid entity identifier. + * @param entt A valid identifier. * @return An iterator to the given entity if it's found, past the end * iterator otherwise. */ - [[nodiscard]] iterator find(const entity_type entt) const { + [[nodiscard]] iterator find(const entity_type entt) const noexcept { const auto it = *this ? handler->find(entt) : iterator{}; return it != end() && *it == entt ? it : end(); } @@ -308,16 +316,16 @@ public: * @brief Checks if a group is properly initialized. * @return True if the group is properly initialized, false otherwise. */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { + [[nodiscard]] explicit operator bool() const noexcept { return handler != nullptr; } /** * @brief Checks if a group contains an entity. - * @param entt A valid entity identifier. + * @param entt A valid identifier. * @return True if the group contains the given entity, false otherwise. */ - [[nodiscard]] bool contains(const entity_type entt) const { + [[nodiscard]] bool contains(const entity_type entt) const noexcept { return *this && handler->contains(entt); } @@ -332,20 +340,18 @@ public: * error. Attempting to use an entity that doesn't belong to the group * results in undefined behavior. * - * @tparam Component Types of components to get. - * @param entt A valid entity identifier. + * @tparam Type Types of components to get. + * @param entt A valid identifier. * @return The components assigned to the entity. */ - template + template [[nodiscard]] decltype(auto) get(const entity_type entt) const { - ENTT_ASSERT(contains(entt), "Group does not contain entity"); - - if constexpr(sizeof...(Component) == 0) { - return std::tuple_cat(get_as_tuple(*std::get *>(pools), entt)...); - } else if constexpr(sizeof...(Component) == 1) { - return (std::get *>(pools)->get(entt), ...); + if constexpr(sizeof...(Type) == 0) { + return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, pools); + } else if constexpr(sizeof...(Type) == 1) { + return (std::get>(pools)->get(entt), ...); } else { - return std::tuple_cat(get_as_tuple(*std::get *>(pools), entt)...); + return std::tuple_cat(std::get>(pools)->get_as_tuple(entt)...); } } @@ -383,7 +389,7 @@ public: } /** - * @brief Returns an iterable object to use to _visit_ the group. + * @brief Returns an iterable object to use to _visit_ a group. * * The iterable object returns tuples that contain the current entity and a * set of references to its non-empty components. The _constness_ of the @@ -395,8 +401,8 @@ public: * * @return An iterable object to use to _visit_ the group. */ - [[nodiscard]] iterable_group each() const ENTT_NOEXCEPT { - return iterable_group{handler, pools}; + [[nodiscard]] iterable each() const noexcept { + return iterable{{begin(), pools}, {end(), pools}}; } /** @@ -411,23 +417,23 @@ public: * comparison function should be equivalent to one of the following: * * @code{.cpp} - * bool(std::tuple, std::tuple); - * bool(const Component &..., const Component &...); + * bool(std::tuple, std::tuple); + * bool(const Type &..., const Type &...); * bool(const Entity, const Entity); * @endcode * - * Where `Component` are such that they are iterated by the group.
+ * Where `Type` are such that they are iterated by the group.
* Moreover, the comparison function object shall induce a * _strict weak ordering_ on the values. * - * The sort function oject must offer a member function template + * The sort function object must offer a member function template * `operator()` that accepts three arguments: * * * An iterator to the first element of the range to sort. * * An iterator past the last element of the range to sort. * * A comparison function to use to compare the elements. * - * @tparam Component Optional types of components to compare. + * @tparam Type Optional types of components to compare. * @tparam Compare Type of comparison function object. * @tparam Sort Type of sort function object. * @tparam Args Types of arguments to forward to the sort function object. @@ -435,20 +441,22 @@ public: * @param algo A valid sort function object. * @param args Arguments to forward to the sort function object, if any. */ - template - void sort(Compare compare, Sort algo = Sort{}, Args &&... args) { + template + void sort(Compare compare, Sort algo = Sort{}, Args &&...args) { if(*this) { - if constexpr(sizeof...(Component) == 0) { + if constexpr(sizeof...(Type) == 0) { static_assert(std::is_invocable_v, "Invalid comparison function"); handler->sort(std::move(compare), std::move(algo), std::forward(args)...); - } else if constexpr(sizeof...(Component) == 1) { - handler->sort([this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) { - return compare((std::get *>(pools)->get(lhs), ...), (std::get *>(pools)->get(rhs), ...)); - }, std::move(algo), std::forward(args)...); } else { - handler->sort([this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) { - return compare(std::forward_as_tuple(std::get *>(pools)->get(lhs)...), std::forward_as_tuple(std::get *>(pools)->get(rhs)...)); - }, std::move(algo), std::forward(args)...); + auto comp = [this, &compare](const entity_type lhs, const entity_type rhs) { + if constexpr(sizeof...(Type) == 1) { + return compare((std::get>(pools)->get(lhs), ...), (std::get>(pools)->get(rhs), ...)); + } else { + return compare(std::forward_as_tuple(std::get>(pools)->get(lhs)...), std::forward_as_tuple(std::get>(pools)->get(rhs)...)); + } + }; + + handler->sort(std::move(comp), std::move(algo), std::forward(args)...); } } } @@ -467,206 +475,112 @@ public: * can quickly ruin the order imposed to the pool of entities shared between * the non-owning groups. * - * @tparam Component Type of component to use to impose the order. + * @tparam Type Type of component to use to impose the order. */ - template + template void sort() const { if(*this) { - handler->respect(*std::get *>(pools)); + handler->respect(*std::get>(pools)); } } private: - basic_common_type * const handler; - const std::tuple *...> pools; + base_type *const handler; + const std::tuple pools; }; - /** * @brief Owning group. * - * Owning groups return all entities and only the entities that have at least - * the given components. Moreover: + * Owning groups returns all entities and only the entities that are at + * least in the given storage. Moreover: * * * It's guaranteed that the entity list is tightly packed in memory for fast * iterations. - * * It's guaranteed that the lists of owned components are tightly packed in - * memory for even faster iterations and to allow direct access. - * * They stay true to the order of the owned components and all instances have - * the same order in memory. + * * It's guaranteed that all components in the owned storage are tightly packed + * in memory for even faster iterations and to allow direct access. + * * They stay true to the order of the owned storage and all instances have the + * same order in memory. * - * The more types of components are owned by a group, the faster it is to - * iterate them. + * The more types of storage are owned, the faster it is to iterate a group. * * @b Important * * Iterators aren't invalidated if: * - * * New instances of the given components are created and assigned to entities. - * * The entity currently pointed is modified (as an example, if one of the - * given components is removed from the entity to which the iterator points). + * * New elements are added to the storage. + * * The entity currently pointed is modified (for example, components are added + * or removed from it). * * The entity currently pointed is destroyed. * * In all other cases, modifying the pools iterated by the group in any way * invalidates all the iterators and using them results in undefined behavior. * - * @note - * Groups share references to the underlying data structures of the registry - * that generated them. Therefore any change to the entities and to the - * components made by means of the registry are immediately reflected by all the - * groups. - * Moreover, sorting an owning group affects all the instance of the same group - * (it means that users don't have to call `sort` on each instance to sort all - * of them because they share the underlying data structure). - * - * @warning - * Lifetime of a group must not overcome that of the registry that generated it. - * In any other case, attempting to use a group results in undefined behavior. - * - * @tparam Entity A valid entity type (see entt_traits for more details). - * @tparam Exclude Types of components used to filter the group. - * @tparam Get Types of components observed by the group. - * @tparam Owned Types of components owned by the group. + * @tparam Owned Types of storage _owned_ by the group. + * @tparam Get Types of storage _observed_ by the group. + * @tparam Exclude Types of storage used to filter the group. */ -template -class basic_group, get_t, Owned...> final { - /*! @brief A registry is allowed to create groups. */ - friend class basic_registry; +template +class basic_group, get_t, exclude_t> { + using underlying_type = std::common_type_t; + using basic_common_type = std::common_type_t; - using basic_common_type = basic_sparse_set; - - template - using storage_type = constness_as_t>::storage_type, Component>; - - class iterable final { - template - struct iterable_iterator; - - template - struct iterable_iterator> final { - using difference_type = std::ptrdiff_t; - using value_type = decltype(std::tuple_cat(std::tuple{}, std::declval().get({}))); - using pointer = void; - using reference = value_type; - using iterator_category = std::input_iterator_tag; - - template - iterable_iterator(It from, const std::tuple &other, const std::tuple *...> &cpools) ENTT_NOEXCEPT - : it{from}, - owned{std::get(other)...}, - get{cpools} - {} - - iterable_iterator & operator++() ENTT_NOEXCEPT { - return ++it, (++std::get(owned), ...), *this; - } - - iterable_iterator operator++(int) ENTT_NOEXCEPT { - iterable_iterator orig = *this; - return ++(*this), orig; - } - - [[nodiscard]] reference operator*() const ENTT_NOEXCEPT { - return std::tuple_cat( - std::make_tuple(*it), - std::forward_as_tuple(*std::get(owned)...), - get_as_tuple(*std::get *>(get), *it)... - ); - } - - [[nodiscard]] bool operator==(const iterable_iterator &other) const ENTT_NOEXCEPT { - return other.it == it; - } - - [[nodiscard]] bool operator!=(const iterable_iterator &other) const ENTT_NOEXCEPT { - return !(*this == other); - } - - private: - It it; - std::tuple owned; - std::tuple *...> get; - }; - - public: - using iterator = iterable_iterator< - typename basic_common_type::iterator, - type_list_cat_t>().get({}))>, type_list<>, type_list>().end())>>...> - >; - using reverse_iterator = iterable_iterator< - typename basic_common_type::reverse_iterator, - type_list_cat_t>().get({}))>, type_list<>, type_list>().rbegin())>>...> - >; - - iterable(std::tuple *..., storage_type *...> cpools, const std::size_t * const extent) - : pools{cpools}, - length{extent} - {} - - [[nodiscard]] iterator begin() const ENTT_NOEXCEPT { - return length ? iterator{ - std::get<0>(pools)->basic_common_type::end() - *length, - std::make_tuple((std::get *>(pools)->end() - *length)...), - std::make_tuple(std::get *>(pools)...) - } : iterator{{}, std::make_tuple(decltype(std::get *>(pools)->end()){}...), std::make_tuple(std::get *>(pools)...)}; - } - - [[nodiscard]] iterator end() const ENTT_NOEXCEPT { - return length ? iterator{ - std::get<0>(pools)->basic_common_type::end(), - std::make_tuple((std::get *>(pools)->end())...), - std::make_tuple(std::get *>(pools)...) - } : iterator{{}, std::make_tuple(decltype(std::get *>(pools)->end()){}...), std::make_tuple(std::get *>(pools)...)}; - } - - [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT { - return length ? reverse_iterator{ - std::get<0>(pools)->basic_common_type::rbegin(), - std::make_tuple((std::get *>(pools)->rbegin())...), - std::make_tuple(std::get *>(pools)...) - } : reverse_iterator{{}, std::make_tuple(decltype(std::get *>(pools)->rbegin()){}...), std::make_tuple(std::get *>(pools)...)}; - } - - [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT { - return length ? reverse_iterator{ - std::get<0>(pools)->basic_common_type::rbegin() + *length, - std::make_tuple((std::get *>(pools)->rbegin() + *length)...), - std::make_tuple(std::get *>(pools)...) - } : reverse_iterator{{}, std::make_tuple(decltype(std::get *>(pools)->rbegin()){}...), std::make_tuple(std::get *>(pools)...)}; - } - - private: - const std::tuple *..., storage_type *...> pools; - const std::size_t * const length; - }; - - basic_group(const std::size_t &extent, storage_type &... opool, storage_type &... gpool) ENTT_NOEXCEPT - : pools{&opool..., &gpool...}, - length{&extent} - {} + template + static constexpr std::size_t index_of = type_list_index_v, type_list>; public: /*! @brief Underlying entity identifier. */ - using entity_type = Entity; + using entity_type = underlying_type; /*! @brief Unsigned integer type. */ using size_type = std::size_t; + /*! @brief Common type among all storage types. */ + using base_type = basic_common_type; /*! @brief Random access iterator type. */ - using iterator = typename basic_common_type::iterator; + using iterator = typename base_type::iterator; /*! @brief Reversed iterator type. */ - using reverse_iterator = typename basic_common_type::reverse_iterator; + using reverse_iterator = typename base_type::reverse_iterator; /*! @brief Iterable group type. */ - using iterable_group = iterable; + using iterable = iterable_adaptor, get_t>>; /*! @brief Default constructor to use to create empty, invalid groups. */ - basic_group() ENTT_NOEXCEPT - : length{} - {} + basic_group() noexcept + : length{} {} /** - * @brief Returns the number of entities that have the given components. - * @return Number of entities that have the given components. + * @brief Constructs a group from a set of storage classes. + * @param extent The actual number of entities to iterate. + * @param opool Storage types to iterate _owned_ by the group. + * @param gpool Storage types to iterate _observed_ by the group. */ - [[nodiscard]] size_type size() const ENTT_NOEXCEPT { + basic_group(const std::size_t &extent, Owned &...opool, Get &...gpool) noexcept + : pools{&opool..., &gpool...}, + length{&extent} {} + + /** + * @brief Returns the storage for a given component type. + * @tparam Type Type of component of which to return the storage. + * @return The storage for the given component type. + */ + template + [[nodiscard]] decltype(auto) storage() const noexcept { + return storage>(); + } + + /** + * @brief Returns the storage for a given index. + * @tparam Index Index of the storage to return. + * @return The storage for the given index. + */ + template + [[nodiscard]] decltype(auto) storage() const noexcept { + return *std::get(pools); + } + + /** + * @brief Returns the number of entities that that are part of the group. + * @return Number of entities that that are part of the group. + */ + [[nodiscard]] size_type size() const noexcept { return *this ? *length : size_type{}; } @@ -674,38 +588,10 @@ public: * @brief Checks whether a group is empty. * @return True if the group is empty, false otherwise. */ - [[nodiscard]] bool empty() const ENTT_NOEXCEPT { + [[nodiscard]] bool empty() const noexcept { return !*this || !*length; } - /** - * @brief Direct access to the raw representation offered by the storage. - * - * @warning - * This function is only available for owned types. - * - * @tparam Component Type of component in which one is interested. - * @return A pointer to the array of components. - */ - template - [[nodiscard]] auto raw() const ENTT_NOEXCEPT { - static_assert((std::is_same_v || ...), "Non-owned type"); - auto *cpool = std::get *>(pools); - return cpool ? cpool->raw() : decltype(cpool->raw()){}; - } - - /** - * @brief Direct access to the list of entities. - * - * The returned pointer is such that range `[data(), data() + size())` is - * always a valid range, even if the container is empty. - * - * @return A pointer to the array of entities. - */ - [[nodiscard]] auto data() const ENTT_NOEXCEPT { - return *this ? std::get<0>(pools)->data() : nullptr; - } - /** * @brief Returns an iterator to the first entity of the group. * @@ -714,8 +600,8 @@ public: * * @return An iterator to the first entity of the group. */ - [[nodiscard]] iterator begin() const ENTT_NOEXCEPT { - return *this ? (std::get<0>(pools)->basic_common_type::end() - *length) : iterator{}; + [[nodiscard]] iterator begin() const noexcept { + return *this ? (std::get<0>(pools)->base_type::end() - *length) : iterator{}; } /** @@ -728,8 +614,8 @@ public: * @return An iterator to the entity following the last entity of the * group. */ - [[nodiscard]] iterator end() const ENTT_NOEXCEPT { - return *this ? std::get<0>(pools)->basic_common_type::end() : iterator{}; + [[nodiscard]] iterator end() const noexcept { + return *this ? std::get<0>(pools)->base_type::end() : iterator{}; } /** @@ -740,8 +626,8 @@ public: * * @return An iterator to the first entity of the reversed group. */ - [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT { - return *this ? std::get<0>(pools)->basic_common_type::rbegin() : reverse_iterator{}; + [[nodiscard]] reverse_iterator rbegin() const noexcept { + return *this ? std::get<0>(pools)->base_type::rbegin() : reverse_iterator{}; } /** @@ -755,8 +641,8 @@ public: * @return An iterator to the entity following the last entity of the * reversed group. */ - [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT { - return *this ? (std::get<0>(pools)->basic_common_type::rbegin() + *length) : reverse_iterator{}; + [[nodiscard]] reverse_iterator rend() const noexcept { + return *this ? (std::get<0>(pools)->base_type::rbegin() + *length) : reverse_iterator{}; } /** @@ -764,7 +650,7 @@ public: * @return The first entity of the group if one exists, the null entity * otherwise. */ - [[nodiscard]] entity_type front() const { + [[nodiscard]] entity_type front() const noexcept { const auto it = begin(); return it != end() ? *it : null; } @@ -774,18 +660,18 @@ public: * @return The last entity of the group if one exists, the null entity * otherwise. */ - [[nodiscard]] entity_type back() const { + [[nodiscard]] entity_type back() const noexcept { const auto it = rbegin(); return it != rend() ? *it : null; } /** * @brief Finds an entity. - * @param entt A valid entity identifier. + * @param entt A valid identifier. * @return An iterator to the given entity if it's found, past the end * iterator otherwise. */ - [[nodiscard]] iterator find(const entity_type entt) const { + [[nodiscard]] iterator find(const entity_type entt) const noexcept { const auto it = *this ? std::get<0>(pools)->find(entt) : iterator{}; return it != end() && it >= begin() && *it == entt ? it : end(); } @@ -803,16 +689,16 @@ public: * @brief Checks if a group is properly initialized. * @return True if the group is properly initialized, false otherwise. */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { + [[nodiscard]] explicit operator bool() const noexcept { return length != nullptr; } /** * @brief Checks if a group contains an entity. - * @param entt A valid entity identifier. + * @param entt A valid identifier. * @return True if the group contains the given entity, false otherwise. */ - [[nodiscard]] bool contains(const entity_type entt) const { + [[nodiscard]] bool contains(const entity_type entt) const noexcept { return *this && std::get<0>(pools)->contains(entt) && (std::get<0>(pools)->index(entt) < (*length)); } @@ -827,20 +713,18 @@ public: * error. Attempting to use an entity that doesn't belong to the group * results in undefined behavior. * - * @tparam Component Types of components to get. - * @param entt A valid entity identifier. + * @tparam Type Types of components to get. + * @param entt A valid identifier. * @return The components assigned to the entity. */ - template + template [[nodiscard]] decltype(auto) get(const entity_type entt) const { - ENTT_ASSERT(contains(entt), "Group does not contain entity"); - - if constexpr(sizeof...(Component) == 0) { - return std::tuple_cat(get_as_tuple(*std::get *>(pools), entt)..., get_as_tuple(*std::get *>(pools), entt)...); - } else if constexpr(sizeof...(Component) == 1) { - return (std::get *>(pools)->get(entt), ...); + if constexpr(sizeof...(Type) == 0) { + return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, pools); + } else if constexpr(sizeof...(Type) == 1) { + return (std::get>(pools)->get(entt), ...); } else { - return std::tuple_cat(get_as_tuple(*std::get *>(pools), entt)...); + return std::tuple_cat(std::get>(pools)->get_as_tuple(entt)...); } } @@ -872,13 +756,13 @@ public: if constexpr(is_applicable_v{}, std::declval().get({})))>) { std::apply(func, args); } else { - std::apply([&func](auto, auto &&... less) { func(std::forward(less)...); }, args); + std::apply([&func](auto, auto &&...less) { func(std::forward(less)...); }, args); } } } /** - * @brief Returns an iterable object to use to _visit_ the group. + * @brief Returns an iterable object to use to _visit_ a group. * * The iterable object returns tuples that contain the current entity and a * set of references to its non-empty components. The _constness_ of the @@ -890,8 +774,8 @@ public: * * @return An iterable object to use to _visit_ the group. */ - [[nodiscard]] iterable_group each() const ENTT_NOEXCEPT { - return iterable_group{pools, length}; + [[nodiscard]] iterable each() const noexcept { + return {{begin(), pools}, {end(), pools}}; } /** @@ -906,24 +790,24 @@ public: * comparison function should be equivalent to one of the following: * * @code{.cpp} - * bool(std::tuple, std::tuple); - * bool(const Component &, const Component &); + * bool(std::tuple, std::tuple); + * bool(const Type &, const Type &); * bool(const Entity, const Entity); * @endcode * - * Where `Component` are either owned types or not but still such that they - * are iterated by the group.
+ * Where `Type` are either owned types or not but still such that they are + * iterated by the group.
* Moreover, the comparison function object shall induce a * _strict weak ordering_ on the values. * - * The sort function oject must offer a member function template + * The sort function object must offer a member function template * `operator()` that accepts three arguments: * * * An iterator to the first element of the range to sort. * * An iterator past the last element of the range to sort. * * A comparison function to use to compare the elements. * - * @tparam Component Optional types of components to compare. + * @tparam Type Optional types of components to compare. * @tparam Compare Type of comparison function object. * @tparam Sort Type of sort function object. * @tparam Args Types of arguments to forward to the sort function object. @@ -931,39 +815,38 @@ public: * @param algo A valid sort function object. * @param args Arguments to forward to the sort function object, if any. */ - template - void sort(Compare compare, Sort algo = Sort{}, Args &&... args) const { - auto *cpool = std::get<0>(pools); - - if constexpr(sizeof...(Component) == 0) { + template + void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const { + if constexpr(sizeof...(Type) == 0) { static_assert(std::is_invocable_v, "Invalid comparison function"); - cpool->sort_n(*length, std::move(compare), std::move(algo), std::forward(args)...); - } else if constexpr(sizeof...(Component) == 1) { - cpool->sort_n(*length, [this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) { - return compare((std::get *>(pools)->get(lhs), ...), (std::get *>(pools)->get(rhs), ...)); - }, std::move(algo), std::forward(args)...); + std::get<0>(pools)->sort_n(*length, std::move(compare), std::move(algo), std::forward(args)...); } else { - cpool->sort_n(*length, [this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) { - return compare(std::forward_as_tuple(std::get *>(pools)->get(lhs)...), std::forward_as_tuple(std::get *>(pools)->get(rhs)...)); - }, std::move(algo), std::forward(args)...); + auto comp = [this, &compare](const entity_type lhs, const entity_type rhs) { + if constexpr(sizeof...(Type) == 1) { + return compare((std::get>(pools)->get(lhs), ...), (std::get>(pools)->get(rhs), ...)); + } else { + return compare(std::forward_as_tuple(std::get>(pools)->get(lhs)...), std::forward_as_tuple(std::get>(pools)->get(rhs)...)); + } + }; + + std::get<0>(pools)->sort_n(*length, std::move(comp), std::move(algo), std::forward(args)...); } - [this](auto *head, auto *... other) { + std::apply([this](auto *head, auto *...other) { for(auto next = *length; next; --next) { const auto pos = next - 1; [[maybe_unused]] const auto entt = head->data()[pos]; - (other->swap(other->data()[pos], entt), ...); + (other->swap_elements(other->data()[pos], entt), ...); } - }(std::get *>(pools)...); + }, + pools); } private: - const std::tuple *..., storage_type *...> pools; - const size_type * const length; + const std::tuple pools; + const size_type *const length; }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/entity/handle.hpp b/LiteLoader/third-party/include/entt/entity/handle.hpp index 4f18fed..a42aeb0 100644 --- a/LiteLoader/third-party/include/entt/entity/handle.hpp +++ b/LiteLoader/third-party/include/entt/entity/handle.hpp @@ -1,31 +1,107 @@ #ifndef ENTT_ENTITY_HANDLE_HPP #define ENTT_ENTITY_HANDLE_HPP - +#include #include #include #include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/type_traits.hpp" +#include "../core/iterator.hpp" +#include "../core/type_traits.hpp" +#include "entity.hpp" #include "fwd.hpp" -#include "registry.hpp" - namespace entt { +/** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + +namespace internal { + +template +class handle_storage_iterator final { + template + friend class handle_storage_iterator; + + using underlying_type = std::remove_reference_t; + using entity_type = typename underlying_type::entity_type; + +public: + using value_type = typename std::iterator_traits::value_type; + using pointer = input_iterator_pointer; + using reference = value_type; + using difference_type = std::ptrdiff_t; + using iterator_category = std::input_iterator_tag; + + constexpr handle_storage_iterator() noexcept + : entt{null}, + it{}, + last{} {} + + constexpr handle_storage_iterator(entity_type value, It from, It to) noexcept + : entt{value}, + it{from}, + last{to} { + while(it != last && !it->second.contains(entt)) { ++it; } + } + + constexpr handle_storage_iterator &operator++() noexcept { + while(++it != last && !it->second.contains(entt)) {} + return *this; + } + + constexpr handle_storage_iterator operator++(int) noexcept { + handle_storage_iterator orig = *this; + return ++(*this), orig; + } + + [[nodiscard]] constexpr reference operator*() const noexcept { + return *it; + } + + [[nodiscard]] constexpr pointer operator->() const noexcept { + return operator*(); + } + + template + friend constexpr bool operator==(const handle_storage_iterator &, const handle_storage_iterator &) noexcept; + +private: + entity_type entt; + It it; + It last; +}; + +template +[[nodiscard]] constexpr bool operator==(const handle_storage_iterator &lhs, const handle_storage_iterator &rhs) noexcept { + return lhs.it == rhs.it; +} + +template +[[nodiscard]] constexpr bool operator!=(const handle_storage_iterator &lhs, const handle_storage_iterator &rhs) noexcept { + return !(lhs == rhs); +} + +} // namespace internal + +/** + * Internal details not to be documented. + * @endcond + */ /** * @brief Non-owning handle to an entity. * * Tiny wrapper around a registry and an entity. * - * @tparam Entity A valid entity type (see entt_traits for more details). - * @tparam Type Types to which to restrict the scope of a handle. + * @tparam Registry Basic registry type. + * @tparam Scope Types to which to restrict the scope of a handle. */ -template +template struct basic_handle { /*! @brief Type of registry accepted by the handle. */ - using registry_type = constness_as_t>, Entity>; + using registry_type = Registry; /*! @brief Underlying entity identifier. */ using entity_type = typename registry_type::entity_type; /*! @brief Underlying version type. */ @@ -34,29 +110,33 @@ struct basic_handle { using size_type = typename registry_type::size_type; /*! @brief Constructs an invalid handle. */ - basic_handle() ENTT_NOEXCEPT - : reg{}, entt{null} - {} + basic_handle() noexcept + : reg{}, + entt{null} {} /** * @brief Constructs a handle from a given registry and entity. * @param ref An instance of the registry class. - * @param value An entity identifier. + * @param value A valid identifier. */ - basic_handle(registry_type &ref, entity_type value) ENTT_NOEXCEPT - : reg{&ref}, entt{value} - {} + basic_handle(registry_type &ref, entity_type value) noexcept + : reg{&ref}, + entt{value} {} /** - * @brief Compares two handles. - * @tparam Args Template parameters of the handle with which to compare. - * @param other Handle with which to compare. - * @return True if both handles refer to the same registry and the same - * entity, false otherwise. + * @brief Returns an iterable object to use to _visit_ a handle. + * + * The iterable object returns a pair that contains the name and a reference + * to the current storage.
+ * Returned storage are those that contain the entity associated with the + * handle. + * + * @return An iterable object to use to _visit_ the handle. */ - template - [[nodiscard]] bool operator==(const basic_handle &other) const ENTT_NOEXCEPT { - return reg == other.registry() && entt == other.entity(); + [[nodiscard]] auto storage() const noexcept { + auto iterable = reg->storage(); + using iterator_type = internal::handle_storage_iterator; + return iterable_adaptor{iterator_type{entt, iterable.begin(), iterable.end()}, iterator_type{entt, iterable.end(), iterable.end()}}; } /** @@ -67,21 +147,18 @@ struct basic_handle { * entity. */ template - operator basic_handle() const ENTT_NOEXCEPT { - static_assert( - (std::is_same_v || std::is_same_v, Entity>) - && (sizeof...(Type) == 0 || ((sizeof...(Args) != 0 && sizeof...(Args) <= sizeof...(Type)) && ... && (type_list_contains_v, Args>))), - "Invalid conversion between different handles" - ); + operator basic_handle() const noexcept { + static_assert(std::is_same_v || std::is_same_v, Registry>, "Invalid conversion between different handles"); + static_assert((sizeof...(Scope) == 0 || ((sizeof...(Args) != 0 && sizeof...(Args) <= sizeof...(Scope)) && ... && (type_list_contains_v, Args>))), "Invalid conversion between different handles"); return reg ? basic_handle{*reg, entt} : basic_handle{}; } /** * @brief Converts a handle to its underlying entity. - * @return An entity identifier. + * @return The contained identifier. */ - [[nodiscard]] operator entity_type() const ENTT_NOEXCEPT { + [[nodiscard]] operator entity_type() const noexcept { return entity(); } @@ -89,7 +166,7 @@ struct basic_handle { * @brief Checks if a handle refers to non-null registry pointer and entity. * @return True if the handle refers to non-null registry and entity, false otherwise. */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { + [[nodiscard]] explicit operator bool() const noexcept { return reg && reg->valid(entt); } @@ -105,7 +182,7 @@ struct basic_handle { * @brief Returns a pointer to the underlying registry, if any. * @return A pointer to the underlying registry, if any. */ - [[nodiscard]] registry_type * registry() const ENTT_NOEXCEPT { + [[nodiscard]] registry_type *registry() const noexcept { return reg; } @@ -113,21 +190,17 @@ struct basic_handle { * @brief Returns the entity associated with a handle. * @return The entity associated with the handle. */ - [[nodiscard]] entity_type entity() const ENTT_NOEXCEPT { + [[nodiscard]] entity_type entity() const noexcept { return entt; } - /** - * @brief Destroys the entity associated with a handle. - * @sa basic_registry::destroy - */ + /*! @brief Destroys the entity associated with a handle. */ void destroy() { reg->destroy(entt); } /** * @brief Destroys the entity associated with a handle. - * @sa basic_registry::destroy * @param version A desired version upon destruction. */ void destroy(const version_type version) { @@ -136,103 +209,79 @@ struct basic_handle { /** * @brief Assigns the given component to a handle. - * @sa basic_registry::emplace * @tparam Component Type of component to create. * @tparam Args Types of arguments to use to construct the component. * @param args Parameters to use to initialize the component. * @return A reference to the newly created component. */ template - decltype(auto) emplace(Args &&... args) const { - static_assert(((sizeof...(Type) == 0) || ... || std::is_same_v), "Invalid type"); + decltype(auto) emplace(Args &&...args) const { + static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v), "Invalid type"); return reg->template emplace(entt, std::forward(args)...); } /** * @brief Assigns or replaces the given component for a handle. - * @sa basic_registry::emplace_or_replace * @tparam Component Type of component to assign or replace. * @tparam Args Types of arguments to use to construct the component. * @param args Parameters to use to initialize the component. * @return A reference to the newly created component. */ template - decltype(auto) emplace_or_replace(Args &&... args) const { - static_assert(((sizeof...(Type) == 0) || ... || std::is_same_v), "Invalid type"); + decltype(auto) emplace_or_replace(Args &&...args) const { + static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v), "Invalid type"); return reg->template emplace_or_replace(entt, std::forward(args)...); } /** * @brief Patches the given component for a handle. - * @sa basic_registry::patch * @tparam Component Type of component to patch. * @tparam Func Types of the function objects to invoke. * @param func Valid function objects. * @return A reference to the patched component. */ template - decltype(auto) patch(Func &&... func) const { - static_assert(((sizeof...(Type) == 0) || ... || std::is_same_v), "Invalid type"); + decltype(auto) patch(Func &&...func) const { + static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v), "Invalid type"); return reg->template patch(entt, std::forward(func)...); } /** * @brief Replaces the given component for a handle. - * @sa basic_registry::replace * @tparam Component Type of component to replace. * @tparam Args Types of arguments to use to construct the component. * @param args Parameters to use to initialize the component. * @return A reference to the component being replaced. */ template - decltype(auto) replace(Args &&... args) const { - static_assert(((sizeof...(Type) == 0) || ... || std::is_same_v), "Invalid type"); + decltype(auto) replace(Args &&...args) const { + static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v), "Invalid type"); return reg->template replace(entt, std::forward(args)...); } /** * @brief Removes the given components from a handle. - * @sa basic_registry::remove * @tparam Component Types of components to remove. * @return The number of components actually removed. */ template size_type remove() const { - static_assert(sizeof...(Type) == 0 || (type_list_contains_v, Component> && ...), "Invalid type"); + static_assert(sizeof...(Scope) == 0 || (type_list_contains_v, Component> && ...), "Invalid type"); return reg->template remove(entt); } /** * @brief Erases the given components from a handle. - * @sa basic_registry::erase * @tparam Component Types of components to erase. */ template void erase() const { - static_assert(sizeof...(Type) == 0 || (type_list_contains_v, Component> && ...), "Invalid type"); + static_assert(sizeof...(Scope) == 0 || (type_list_contains_v, Component> && ...), "Invalid type"); reg->template erase(entt); } - /*! @copydoc remove */ - template - [[deprecated("Use ::remove instead")]] - size_type remove_if_exists() const { - return remove(); - } - - /** - * @brief Removes all the components from a handle and makes it orphaned. - * @sa basic_registry::remove_all - */ - [[deprecated("No longer supported")]] - void remove_all() const { - static_assert(sizeof...(Type) == 0, "Invalid operation"); - reg->remove_all(entt); - } - /** * @brief Checks if a handle has all the given components. - * @sa basic_registry::all_of * @tparam Component Components for which to perform the check. * @return True if the handle has all the components, false otherwise. */ @@ -243,7 +292,6 @@ struct basic_handle { /** * @brief Checks if a handle has at least one of the given components. - * @sa basic_registry::any_of * @tparam Component Components for which to perform the check. * @return True if the handle has at least one of the given components, * false otherwise. @@ -255,39 +303,36 @@ struct basic_handle { /** * @brief Returns references to the given components for a handle. - * @sa basic_registry::get * @tparam Component Types of components to get. * @return References to the components owned by the handle. */ template [[nodiscard]] decltype(auto) get() const { - static_assert(sizeof...(Type) == 0 || (type_list_contains_v, Component> && ...), "Invalid type"); + static_assert(sizeof...(Scope) == 0 || (type_list_contains_v, Component> && ...), "Invalid type"); return reg->template get(entt); } /** * @brief Returns a reference to the given component for a handle. - * @sa basic_registry::get_or_emplace * @tparam Component Type of component to get. * @tparam Args Types of arguments to use to construct the component. * @param args Parameters to use to initialize the component. * @return Reference to the component owned by the handle. */ template - [[nodiscard]] decltype(auto) get_or_emplace(Args &&... args) const { - static_assert(((sizeof...(Type) == 0) || ... || std::is_same_v), "Invalid type"); + [[nodiscard]] decltype(auto) get_or_emplace(Args &&...args) const { + static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v), "Invalid type"); return reg->template get_or_emplace(entt, std::forward(args)...); } /** * @brief Returns pointers to the given components for a handle. - * @sa basic_registry::try_get * @tparam Component Types of components to get. * @return Pointers to the components owned by the handle. */ template [[nodiscard]] auto try_get() const { - static_assert(sizeof...(Type) == 0 || (type_list_contains_v, Component> && ...), "Invalid type"); + static_assert(sizeof...(Scope) == 0 || (type_list_contains_v, Component> && ...), "Invalid type"); return reg->template try_get(entt); } @@ -299,57 +344,39 @@ struct basic_handle { return reg->orphan(entt); } - /** - * @brief Visits a handle and returns the types for its components. - * @sa basic_registry::visit - * @tparam Func Type of the function object to invoke. - * @param func A valid function object. - */ - template - void visit(Func &&func) const { - reg->visit(entt, std::forward(func)); - } - private: registry_type *reg; entity_type entt; }; +/** + * @brief Compares two handles. + * @tparam Args Scope of the first handle. + * @tparam Other Scope of the second handle. + * @param lhs A valid handle. + * @param rhs A valid handle. + * @return True if both handles refer to the same registry and the same + * entity, false otherwise. + */ +template +[[nodiscard]] bool operator==(const basic_handle &lhs, const basic_handle &rhs) noexcept { + return lhs.registry() == rhs.registry() && lhs.entity() == rhs.entity(); +} /** * @brief Compares two handles. - * @tparam Type A valid entity type (see entt_traits for more details). - * @tparam Other A valid entity type (see entt_traits for more details). + * @tparam Args Scope of the first handle. + * @tparam Other Scope of the second handle. * @param lhs A valid handle. * @param rhs A valid handle. * @return False if both handles refer to the same registry and the same * entity, true otherwise. */ -template -bool operator!=(const basic_handle &lhs, const basic_handle &rhs) ENTT_NOEXCEPT { +template +[[nodiscard]] bool operator!=(const basic_handle &lhs, const basic_handle &rhs) noexcept { return !(lhs == rhs); } - -/** - * @brief Deduction guide. - * @tparam Entity A valid entity type (see entt_traits for more details). - */ -template -basic_handle(basic_registry &, Entity) --> basic_handle; - - -/** - * @brief Deduction guide. - * @tparam Entity A valid entity type (see entt_traits for more details). - */ -template -basic_handle(const basic_registry &, Entity) --> basic_handle; - - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/entity/helper.hpp b/LiteLoader/third-party/include/entt/entity/helper.hpp index 26220c8..7440937 100644 --- a/LiteLoader/third-party/include/entt/entity/helper.hpp +++ b/LiteLoader/third-party/include/entt/entity/helper.hpp @@ -1,139 +1,116 @@ #ifndef ENTT_ENTITY_HELPER_HPP #define ENTT_ENTITY_HELPER_HPP - +#include #include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/fwd.hpp" -#include "third-party/include/entt/core/type_traits.hpp" -#include "third-party/include/entt/signal/delegate.hpp" -#include "registry.hpp" +#include "../core/fwd.hpp" +#include "../core/type_traits.hpp" +#include "../signal/delegate.hpp" +#include "component.hpp" #include "fwd.hpp" - +#include "group.hpp" +#include "view.hpp" namespace entt { - /** * @brief Converts a registry to a view. - * @tparam Entity A valid entity type (see entt_traits for more details). + * @tparam Registry Basic registry type. */ -template -struct as_view { - /*! @brief Underlying entity identifier. */ - using entity_type = std::remove_const_t; +template +class as_view { + template + auto dispatch(get_t, exclude_t) const { + return reg.template view...>(exclude_t...>{}); + } + +public: /*! @brief Type of registry to convert. */ - using registry_type = constness_as_t, Entity>; + using registry_type = Registry; + /*! @brief Underlying entity identifier. */ + using entity_type = std::remove_const_t; /** * @brief Constructs a converter for a given registry. * @param source A valid reference to a registry. */ - as_view(registry_type &source) ENTT_NOEXCEPT: reg{source} {} + as_view(registry_type &source) noexcept + : reg{source} {} /** * @brief Conversion function from a registry to a view. - * @tparam Exclude Types of components used to filter the view. - * @tparam Component Type of components used to construct the view. + * @tparam Get Type of storage used to construct the view. + * @tparam Exclude Types of storage used to filter the view. * @return A newly created view. */ - template - operator basic_view() const { - return reg.template view(Exclude{}); + template + operator basic_view() const { + return dispatch(Get{}, Exclude{}); } private: registry_type ® }; - -/** - * @brief Deduction guide. - * @tparam Entity A valid entity type (see entt_traits for more details). - */ -template -as_view(basic_registry &) -> as_view; - - -/** - * @brief Deduction guide. - * @tparam Entity A valid entity type (see entt_traits for more details). - */ -template -as_view(const basic_registry &) -> as_view; - - /** * @brief Converts a registry to a group. - * @tparam Entity A valid entity type (see entt_traits for more details). + * @tparam Registry Basic registry type. */ -template -struct as_group { - /*! @brief Underlying entity identifier. */ - using entity_type = std::remove_const_t; +template +class as_group { + template + auto dispatch(owned_t, get_t, exclude_t) const { + if constexpr(std::is_const_v) { + return reg.template group_if_exists(get_t{}, exclude_t{}); + } else { + return reg.template group...>(get_t...>{}, exclude_t...>{}); + } + } + +public: /*! @brief Type of registry to convert. */ - using registry_type = constness_as_t, Entity>; + using registry_type = Registry; + /*! @brief Underlying entity identifier. */ + using entity_type = std::remove_const_t; /** * @brief Constructs a converter for a given registry. * @param source A valid reference to a registry. */ - as_group(registry_type &source) ENTT_NOEXCEPT: reg{source} {} + as_group(registry_type &source) noexcept + : reg{source} {} /** * @brief Conversion function from a registry to a group. - * @tparam Exclude Types of components used to filter the group. - * @tparam Get Types of components observed by the group. - * @tparam Owned Types of components owned by the group. + * @tparam Owned Types of _owned_ by the group. + * @tparam Get Types of storage _observed_ by the group. + * @tparam Exclude Types of storage used to filter the group. * @return A newly created group. */ - template - operator basic_group() const { - if constexpr(std::is_const_v) { - return reg.template group_if_exists(Get{}, Exclude{}); - } else { - return reg.template group(Get{}, Exclude{}); - } + template + operator basic_group() const { + return dispatch(Owned{}, Get{}, Exclude{}); } private: registry_type ® }; - -/** - * @brief Deduction guide. - * @tparam Entity A valid entity type (see entt_traits for more details). - */ -template -as_group(basic_registry &) -> as_group; - - -/** - * @brief Deduction guide. - * @tparam Entity A valid entity type (see entt_traits for more details). - */ -template -as_group(const basic_registry &) -> as_group; - - - /** * @brief Helper to create a listener that directly invokes a member function. * @tparam Member Member function to invoke on a component of the given type. - * @tparam Entity A valid entity type (see entt_traits for more details). + * @tparam Registry Basic registry type. * @param reg A registry that contains the given entity and its components. * @param entt Entity from which to get the component. */ -template -void invoke(basic_registry ®, const Entity entt) { +template>> +void invoke(Registry ®, const typename Registry::entity_type entt) { static_assert(std::is_member_function_pointer_v, "Invalid pointer to non-static member function"); - delegate &, const Entity)> func; + delegate func; func.template connect(reg.template get>(entt)); func(reg, entt); } - /** * @brief Returns the entity associated with a given component. * @@ -141,28 +118,27 @@ void invoke(basic_registry ®, const Entity entt) { * Currently, this function only works correctly with the default pool as it * makes assumptions about how the components are laid out. * - * @tparam Entity A valid entity type (see entt_traits for more details). + * @tparam Registry Basic registry type. * @tparam Component Type of component. * @param reg A registry that contains the given entity and its components. * @param instance A valid component instance. * @return The entity associated with the given component. */ -template -Entity to_entity(const basic_registry ®, const Component &instance) { - const auto view = reg.template view(); +template +typename Registry::entity_type to_entity(const Registry ®, const Component &instance) { + const auto &storage = reg.template storage(); + const typename Registry::base_type &base = storage; const auto *addr = std::addressof(instance); - for(auto it = view.rbegin(), last = view.rend(); it < last; it += ENTT_PACKED_PAGE) { - if(const auto dist = (addr - std::addressof(view.template get(*it))); dist >= 0 && dist < ENTT_PACKED_PAGE) { + for(auto it = base.rbegin(), last = base.rend(); it < last; it += component_traits::page_size) { + if(const auto dist = (addr - std::addressof(storage.get(*it))); dist >= 0 && dist < static_cast(component_traits::page_size)) { return *(it + dist); } } - return entt::null; -} - - + return null; } +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/entity/observer.hpp b/LiteLoader/third-party/include/entt/entity/observer.hpp index 027a109..5c1f503 100644 --- a/LiteLoader/third-party/include/entt/entity/observer.hpp +++ b/LiteLoader/third-party/include/entt/entity/observer.hpp @@ -1,30 +1,22 @@ #ifndef ENTT_ENTITY_OBSERVER_HPP #define ENTT_ENTITY_OBSERVER_HPP - -#include #include #include -#include +#include #include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/type_traits.hpp" -#include "third-party/include/entt/signal/delegate.hpp" -#include "registry.hpp" -#include "storage.hpp" -#include "utility.hpp" -#include "entity.hpp" +#include +#include "../core/type_traits.hpp" +#include "../signal/delegate.hpp" #include "fwd.hpp" - +#include "storage.hpp" namespace entt { - /*! @brief Grouping matcher. */ template struct matcher {}; - /** * @brief Collector. * @@ -34,7 +26,6 @@ struct matcher {}; template struct basic_collector; - /** * @brief Collector. * @@ -52,7 +43,7 @@ struct basic_collector<> { * @return The updated collector. */ template - static constexpr auto group(exclude_t = {}) ENTT_NOEXCEPT { + static constexpr auto group(exclude_t = {}) noexcept { return basic_collector, type_list<>, type_list, AllOf...>>{}; } @@ -62,7 +53,7 @@ struct basic_collector<> { * @return The updated collector. */ template - static constexpr auto update() ENTT_NOEXCEPT { + static constexpr auto update() noexcept { return basic_collector, type_list<>, AnyOf>>{}; } }; @@ -87,7 +78,7 @@ struct basic_collector, type_list, Rule * @return The updated collector. */ template - static constexpr auto group(exclude_t = {}) ENTT_NOEXCEPT { + static constexpr auto group(exclude_t = {}) noexcept { return basic_collector, type_list<>, type_list, AllOf...>, current_type, Other...>{}; } @@ -97,7 +88,7 @@ struct basic_collector, type_list, Rule * @return The updated collector. */ template - static constexpr auto update() ENTT_NOEXCEPT { + static constexpr auto update() noexcept { return basic_collector, type_list<>, AnyOf>, current_type, Other...>{}; } @@ -108,17 +99,15 @@ struct basic_collector, type_list, Rule * @return The updated collector. */ template - static constexpr auto where(exclude_t = {}) ENTT_NOEXCEPT { + static constexpr auto where(exclude_t = {}) noexcept { using extended_type = matcher, type_list, Rule...>; return basic_collector{}; } }; - /*! @brief Variable template used to ease the definition of collectors. */ inline constexpr basic_collector<> collector{}; - /** * @brief Observer. * @@ -166,11 +155,11 @@ inline constexpr basic_collector<> collector{}; * from the registry before being destroyed to avoid crashes due to dangling * pointers. * - * @tparam Entity A valid entity type (see entt_traits for more details). + * @tparam Registry Basic registry type. */ -template -class basic_observer { - using payload_type = std::uint32_t; +template +class basic_observer: private basic_storage { + using base_type = basic_storage; template struct matcher_handler; @@ -178,32 +167,32 @@ class basic_observer { template struct matcher_handler, type_list, AnyOf>> { template - static void maybe_valid_if(basic_observer &obs, basic_registry ®, const Entity entt) { + static void maybe_valid_if(basic_observer &obs, Registry ®, const typename Registry::entity_type entt) { if(reg.template all_of(entt) && !reg.template any_of(entt)) { - if(!obs.storage.contains(entt)) { - obs.storage.emplace(entt); + if(!obs.contains(entt)) { + obs.emplace(entt); } - obs.storage.get(entt) |= (1 << Index); + obs.get(entt) |= (1 << Index); } } template - static void discard_if(basic_observer &obs, basic_registry &, const Entity entt) { - if(obs.storage.contains(entt) && !(obs.storage.get(entt) &= (~(1 << Index)))) { - obs.storage.erase(entt); + static void discard_if(basic_observer &obs, Registry &, const typename Registry::entity_type entt) { + if(obs.contains(entt) && !(obs.get(entt) &= (~(1 << Index)))) { + obs.erase(entt); } } template - static void connect(basic_observer &obs, basic_registry ®) { + static void connect(basic_observer &obs, Registry ®) { (reg.template on_destroy().template connect<&discard_if>(obs), ...); (reg.template on_construct().template connect<&discard_if>(obs), ...); reg.template on_update().template connect<&maybe_valid_if>(obs); reg.template on_destroy().template connect<&discard_if>(obs); } - static void disconnect(basic_observer &obs, basic_registry ®) { + static void disconnect(basic_observer &obs, Registry ®) { (reg.template on_destroy().disconnect(obs), ...); (reg.template on_construct().disconnect(obs), ...); reg.template on_update().disconnect(obs); @@ -214,32 +203,33 @@ class basic_observer { template struct matcher_handler, type_list, type_list, AllOf...>> { template - static void maybe_valid_if(basic_observer &obs, basic_registry ®, const Entity entt) { - if([®, entt]() { + static void maybe_valid_if(basic_observer &obs, Registry ®, const typename Registry::entity_type entt) { + auto condition = [®, entt]() { if constexpr(sizeof...(Ignore) == 0) { return reg.template all_of(entt) && !reg.template any_of(entt); } else { return reg.template all_of(entt) && ((std::is_same_v || !reg.template any_of(entt)) && ...) && !reg.template any_of(entt); } - }()) - { - if(!obs.storage.contains(entt)) { - obs.storage.emplace(entt); + }; + + if(condition()) { + if(!obs.contains(entt)) { + obs.emplace(entt); } - obs.storage.get(entt) |= (1 << Index); + obs.get(entt) |= (1 << Index); } } template - static void discard_if(basic_observer &obs, basic_registry &, const Entity entt) { - if(obs.storage.contains(entt) && !(obs.storage.get(entt) &= (~(1 << Index)))) { - obs.storage.erase(entt); + static void discard_if(basic_observer &obs, Registry &, const typename Registry::entity_type entt) { + if(obs.contains(entt) && !(obs.get(entt) &= (~(1 << Index)))) { + obs.erase(entt); } } template - static void connect(basic_observer &obs, basic_registry ®) { + static void connect(basic_observer &obs, Registry ®) { (reg.template on_destroy().template connect<&discard_if>(obs), ...); (reg.template on_construct().template connect<&discard_if>(obs), ...); (reg.template on_construct().template connect<&maybe_valid_if>(obs), ...); @@ -248,7 +238,7 @@ class basic_observer { (reg.template on_construct().template connect<&discard_if>(obs), ...); } - static void disconnect(basic_observer &obs, basic_registry ®) { + static void disconnect(basic_observer &obs, Registry ®) { (reg.template on_destroy().disconnect(obs), ...); (reg.template on_construct().disconnect(obs), ...); (reg.template on_construct().disconnect(obs), ...); @@ -259,30 +249,30 @@ class basic_observer { }; template - static void disconnect(basic_registry ®, basic_observer &obs) { + static void disconnect(Registry ®, basic_observer &obs) { (matcher_handler::disconnect(obs, reg), ...); } template - void connect(basic_registry ®, std::index_sequence) { - static_assert(sizeof...(Matcher) < std::numeric_limits::digits, "Too many matchers"); + void connect(Registry ®, std::index_sequence) { + static_assert(sizeof...(Matcher) < std::numeric_limits::digits, "Too many matchers"); (matcher_handler::template connect(*this, reg), ...); release.template connect<&basic_observer::disconnect>(reg); } public: + /*! Basic registry type. */ + using registry_type = Registry; /*! @brief Underlying entity identifier. */ - using entity_type = Entity; + using entity_type = typename registry_type::entity_type; /*! @brief Unsigned integer type. */ using size_type = std::size_t; /*! @brief Random access iterator type. */ - using iterator = typename basic_sparse_set::iterator; + using iterator = typename registry_type::base_type::iterator; /*! @brief Default constructor. */ basic_observer() - : release{}, - storage{} - {} + : release{} {} /*! @brief Default copy constructor, deleted on purpose. */ basic_observer(const basic_observer &) = delete; @@ -295,9 +285,8 @@ public: * @param reg A valid reference to a registry. */ template - basic_observer(basic_registry ®, basic_collector) - : basic_observer{} - { + basic_observer(registry_type ®, basic_collector) + : basic_observer{} { connect(reg, std::index_sequence_for{}); } @@ -308,13 +297,13 @@ public: * @brief Default copy assignment operator, deleted on purpose. * @return This observer. */ - basic_observer & operator=(const basic_observer &) = delete; + basic_observer &operator=(const basic_observer &) = delete; /** * @brief Default move assignment operator, deleted on purpose. * @return This observer. */ - basic_observer & operator=(basic_observer &&) = delete; + basic_observer &operator=(basic_observer &&) = delete; /** * @brief Connects an observer to a given registry. @@ -322,10 +311,10 @@ public: * @param reg A valid reference to a registry. */ template - void connect(basic_registry ®, basic_collector) { + void connect(registry_type ®, basic_collector) { disconnect(); connect(reg, std::index_sequence_for{}); - storage.clear(); + base_type::clear(); } /*! @brief Disconnects an observer from the registry it keeps track of. */ @@ -340,16 +329,16 @@ public: * @brief Returns the number of elements in an observer. * @return Number of elements. */ - [[nodiscard]] size_type size() const ENTT_NOEXCEPT { - return storage.size(); + [[nodiscard]] size_type size() const noexcept { + return base_type::size(); } /** * @brief Checks whether an observer is empty. * @return True if the observer is empty, false otherwise. */ - [[nodiscard]] bool empty() const ENTT_NOEXCEPT { - return storage.empty(); + [[nodiscard]] bool empty() const noexcept { + return base_type::empty(); } /** @@ -364,8 +353,8 @@ public: * * @return A pointer to the array of entities. */ - [[nodiscard]] const entity_type * data() const ENTT_NOEXCEPT { - return storage.data(); + [[nodiscard]] const entity_type *data() const noexcept { + return base_type::data(); } /** @@ -376,8 +365,8 @@ public: * * @return An iterator to the first entity of the observer. */ - [[nodiscard]] iterator begin() const ENTT_NOEXCEPT { - return storage.basic_sparse_set::begin(); + [[nodiscard]] iterator begin() const noexcept { + return base_type::base_type::begin(); } /** @@ -390,13 +379,13 @@ public: * @return An iterator to the entity following the last entity of the * observer. */ - [[nodiscard]] iterator end() const ENTT_NOEXCEPT { - return storage.basic_sparse_set::end(); + [[nodiscard]] iterator end() const noexcept { + return base_type::base_type::end(); } /*! @brief Clears the underlying container. */ - void clear() ENTT_NOEXCEPT { - storage.clear(); + void clear() noexcept { + base_type::clear(); } /** @@ -436,11 +425,8 @@ public: private: delegate release; - basic_storage storage; }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/entity/organizer.hpp b/LiteLoader/third-party/include/entt/entity/organizer.hpp index f7fe045..ebda20b 100644 --- a/LiteLoader/third-party/include/entt/entity/organizer.hpp +++ b/LiteLoader/third-party/include/entt/entity/organizer.hpp @@ -1,115 +1,98 @@ #ifndef ENTT_ENTITY_ORGANIZER_HPP #define ENTT_ENTITY_ORGANIZER_HPP - #include -#include #include -#include #include #include -#include "third-party/include/entt/core/type_info.hpp" -#include "third-party/include/entt/core/type_traits.hpp" +#include "../core/type_info.hpp" +#include "../core/type_traits.hpp" +#include "../core/utility.hpp" +#include "../graph/adjacency_matrix.hpp" +#include "../graph/flow.hpp" #include "fwd.hpp" #include "helper.hpp" - namespace entt { - /** * @cond TURN_OFF_DOXYGEN * Internal details not to be documented. */ - namespace internal { - template struct is_view: std::false_type {}; -template -struct is_view, Component...>>: std::true_type {}; +template +struct is_view>: std::true_type {}; template inline constexpr bool is_view_v = is_view::value; - template struct unpack_type { using ro = std::conditional_t< - type_list_contains_v> || (std::is_const_v && !type_list_contains_v>), + type_list_contains_v || (std::is_const_v && !type_list_contains_v>), type_list>, - type_list<> - >; + type_list<>>; using rw = std::conditional_t< - type_list_contains_v> || (!std::is_const_v && !type_list_contains_v>), + type_list_contains_v> || (!std::is_const_v && !type_list_contains_v), type_list, - type_list<> - >; + type_list<>>; }; -template -struct unpack_type, type_list> { +template +struct unpack_type, type_list> { using ro = type_list<>; using rw = type_list<>; }; -template -struct unpack_type, type_list> - : unpack_type, type_list> -{}; +template +struct unpack_type, type_list> + : unpack_type, type_list> {}; -template -struct unpack_type, Component...>, type_list> { - using ro = type_list_cat_t, typename unpack_type>::ro...>; - using rw = type_list_cat_t>::rw...>; +template +struct unpack_type, exclude_t>, type_list> { + using ro = type_list_cat_t, typename unpack_type, type_list>::ro...>; + using rw = type_list_cat_t, type_list>::rw...>; }; -template -struct unpack_type, Component...>, type_list> - : unpack_type, Component...>, type_list> -{}; - +template +struct unpack_type, exclude_t>, type_list> + : unpack_type, exclude_t>, type_list> {}; template -struct resource; +struct resource_traits; template -struct resource, type_list> { +struct resource_traits, type_list> { using args = type_list...>; using ro = type_list_cat_t>::ro..., typename unpack_type>::ro...>; using rw = type_list_cat_t>::rw..., typename unpack_type>::rw...>; }; - template -resource...>, type_list> free_function_to_resource(Ret(*)(Args...)); +resource_traits...>, type_list> free_function_to_resource_traits(Ret (*)(Args...)); template -resource...>, type_list> constrained_function_to_resource(Ret(*)(Type &, Args...)); +resource_traits...>, type_list> constrained_function_to_resource_traits(Ret (*)(Type &, Args...)); template -resource...>, type_list> constrained_function_to_resource(Ret(Class:: *)(Args...)); +resource_traits...>, type_list> constrained_function_to_resource_traits(Ret (Class::*)(Args...)); template -resource...>, type_list> constrained_function_to_resource(Ret(Class:: *)(Args...) const); - -template -resource, type_list> to_resource(); - - -} +resource_traits...>, type_list> constrained_function_to_resource_traits(Ret (Class::*)(Args...) const); +} // namespace internal /** * Internal details not to be documented. * @endcond */ - /** * @brief Utility class for creating a static task graph. * @@ -119,13 +102,13 @@ resource, type_list> to_resource(); * goal of the tool. Instead, they are returned to the user in the form of a * graph that allows for safe execution. * - * @tparam Entity A valid entity type (see entt_traits for more details). + * @tparam Registry Basic registry type. */ -template +template class basic_organizer final { - using callback_type = void(const void *, entt::basic_registry &); - using prepare_type = void(entt::basic_registry &); - using dependency_type = std::size_t(const bool, type_info *, const std::size_t); + using callback_type = void(const void *, Registry &); + using prepare_type = void(Registry &); + using dependency_type = std::size_t(const bool, const type_info **, const std::size_t); struct vertex_data final { std::size_t ro_count{}; @@ -135,117 +118,54 @@ class basic_organizer final { callback_type *callback{}; dependency_type *dependency; prepare_type *prepare{}; - type_info info{}; + const type_info *info{}; }; template - [[nodiscard]] static decltype(auto) extract(basic_registry ®) { - if constexpr(std::is_same_v>) { + [[nodiscard]] static decltype(auto) extract(Registry ®) { + if constexpr(std::is_same_v) { return reg; } else if constexpr(internal::is_view_v) { return as_view{reg}; } else { - return reg.template ctx_or_set>(); + return reg.ctx().template emplace>(); } } template - [[nodiscard]] static auto to_args(basic_registry ®, type_list) { + [[nodiscard]] static auto to_args(Registry ®, type_list) { return std::tuple(reg))...>(extract(reg)...); } template - static std::size_t fill_dependencies(type_list, [[maybe_unused]] type_info *buffer, [[maybe_unused]] const std::size_t count) { + static std::size_t fill_dependencies(type_list, [[maybe_unused]] const type_info **buffer, [[maybe_unused]] const std::size_t count) { if constexpr(sizeof...(Type) == 0u) { return {}; } else { - type_info info[sizeof...(Type)]{type_id()...}; - const auto length = (std::min)(count, sizeof...(Type)); - std::copy_n(info, length, buffer); + const type_info *info[sizeof...(Type)]{&type_id()...}; + const auto length = count < sizeof...(Type) ? count : sizeof...(Type); + + for(std::size_t pos{}; pos < length; ++pos) { + buffer[pos] = info[pos]; + } + return length; } } template void track_dependencies(std::size_t index, const bool requires_registry, type_list, type_list) { - dependencies[type_hash>::value()].emplace_back(index, requires_registry || (sizeof...(RO) + sizeof...(RW) == 0u)); - (dependencies[type_hash::value()].emplace_back(index, false), ...); - (dependencies[type_hash::value()].emplace_back(index, true), ...); - } - - [[nodiscard]] std::vector adjacency_matrix() { - const auto length = vertices.size(); - std::vector edges(length * length, false); - - // creates the ajacency matrix - for(const auto &deps: dependencies) { - const auto last = deps.second.cend(); - auto it = deps.second.cbegin(); - - while(it != last) { - if(it->second) { - // rw item - if(auto curr = it++; it != last) { - if(it->second) { - edges[curr->first * length + it->first] = true; - } else { - if(const auto next = std::find_if(it, last, [](const auto &elem) { return elem.second; }); next != last) { - for(; it != next; ++it) { - edges[curr->first * length + it->first] = true; - edges[it->first * length + next->first] = true; - } - } else { - for(; it != next; ++it) { - edges[curr->first * length + it->first] = true; - } - } - } - } - } else { - // ro item, possibly only on first iteration - if(const auto next = std::find_if(it, last, [](const auto &elem) { return elem.second; }); next != last) { - for(; it != next; ++it) { - edges[it->first * length + next->first] = true; - } - } else { - it = last; - } - } - } - } - - // computes the transitive closure - for(std::size_t vk{}; vk < length; ++vk) { - for(std::size_t vi{}; vi < length; ++vi) { - for(std::size_t vj{}; vj < length; ++vj) { - edges[vi * length + vj] = edges[vi * length + vj] || (edges[vi * length + vk] && edges[vk * length + vj]); - } - } - } - - // applies the transitive reduction - for(std::size_t vert{}; vert < length; ++vert) { - edges[vert * length + vert] = false; - } - - for(std::size_t vj{}; vj < length; ++vj) { - for(std::size_t vi{}; vi < length; ++vi) { - if(edges[vi * length + vj]) { - for(std::size_t vk{}; vk < length; ++vk) { - if(edges[vj * length + vk]) { - edges[vi * length + vk] = false; - } - } - } - } - } - - return edges; + builder.bind(static_cast(index)); + builder.set(type_hash::value(), requires_registry || (sizeof...(RO) + sizeof...(RW) == 0u)); + (builder.ro(type_hash::value()), ...); + (builder.rw(type_hash::value()), ...); } public: + /*! Basic registry type. */ + using registry_type = Registry; /*! @brief Underlying entity identifier. */ - using entity_type = Entity; + using entity_type = typename registry_type::entity_type; /*! @brief Unsigned integer type. */ using size_type = std::size_t; /*! @brief Raw task function type. */ @@ -262,8 +182,7 @@ public: vertex(const bool vtype, vertex_data data, std::vector edges) : is_top_level{vtype}, node{std::move(data)}, - reachable{std::move(edges)} - {} + reachable{std::move(edges)} {} /** * @brief Fills a buffer with the type info objects for the writable @@ -272,7 +191,7 @@ public: * @param length The length of the user-supplied buffer. * @return The number of type info objects written to the buffer. */ - size_type ro_dependency(type_info *buffer, const std::size_t length) const ENTT_NOEXCEPT { + size_type ro_dependency(const type_info **buffer, const std::size_t length) const noexcept { return node.dependency(false, buffer, length); } @@ -283,7 +202,7 @@ public: * @param length The length of the user-supplied buffer. * @return The number of type info objects written to the buffer. */ - size_type rw_dependency(type_info *buffer, const std::size_t length) const ENTT_NOEXCEPT { + size_type rw_dependency(const type_info **buffer, const std::size_t length) const noexcept { return node.dependency(true, buffer, length); } @@ -291,7 +210,7 @@ public: * @brief Returns the number of read-only resources of a vertex. * @return The number of read-only resources of the vertex. */ - size_type ro_count() const ENTT_NOEXCEPT { + size_type ro_count() const noexcept { return node.ro_count; } @@ -299,7 +218,7 @@ public: * @brief Returns the number of writable resources of a vertex. * @return The number of writable resources of the vertex. */ - size_type rw_count() const ENTT_NOEXCEPT { + size_type rw_count() const noexcept { return node.rw_count; } @@ -307,7 +226,7 @@ public: * @brief Checks if a vertex is also a top-level one. * @return True if the vertex is a top-level one, false otherwise. */ - bool top_level() const ENTT_NOEXCEPT { + bool top_level() const noexcept { return is_top_level; } @@ -315,15 +234,15 @@ public: * @brief Returns a type info object associated with a vertex. * @return A properly initialized type info object. */ - type_info info() const ENTT_NOEXCEPT { - return node.info; + const type_info &info() const noexcept { + return *node.info; } /** * @brief Returns a user defined name associated with a vertex, if any. * @return The user defined name associated with the vertex, if any. */ - const char * name() const ENTT_NOEXCEPT { + const char *name() const noexcept { return node.name; } @@ -331,7 +250,7 @@ public: * @brief Returns the function associated with a vertex. * @return The function associated with the vertex. */ - function_type * callback() const ENTT_NOEXCEPT { + function_type *callback() const noexcept { return node.callback; } @@ -339,7 +258,7 @@ public: * @brief Returns the payload associated with a vertex, if any. * @return The payload associated with the vertex, if any. */ - const void * data() const ENTT_NOEXCEPT { + const void *data() const noexcept { return node.payload; } @@ -347,7 +266,7 @@ public: * @brief Returns the list of nodes reachable from a given vertex. * @return The list of nodes reachable from the vertex. */ - const std::vector & children() const ENTT_NOEXCEPT { + const std::vector &children() const noexcept { return reachable; } @@ -356,7 +275,7 @@ public: * are properly instantiated before using them. * @param reg A valid registry. */ - void prepare(basic_registry ®) const { + void prepare(registry_type ®) const { node.prepare ? node.prepare(reg) : void(); } @@ -374,25 +293,25 @@ public: */ template void emplace(const char *name = nullptr) { - using resource_type = decltype(internal::free_function_to_resource(Candidate)); - constexpr auto requires_registry = type_list_contains_v>; + using resource_type = decltype(internal::free_function_to_resource_traits(Candidate)); + constexpr auto requires_registry = type_list_contains_v; - callback_type *callback = +[](const void *, basic_registry ®) { + callback_type *callback = +[](const void *, registry_type ®) { std::apply(Candidate, to_args(reg, typename resource_type::args{})); }; - track_dependencies(vertices.size(), requires_registry, typename resource_type::ro{}, typename resource_type::rw{}); - - vertices.push_back({ + vertex_data vdata{ resource_type::ro::size, resource_type::rw::size, name, nullptr, callback, - +[](const bool rw, type_info *buffer, const std::size_t length) { return rw ? fill_dependencies(typename resource_type::rw{}, buffer, length) : fill_dependencies(typename resource_type::ro{}, buffer, length); }, - +[](basic_registry ®) { void(to_args(reg, typename resource_type::args{})); }, - type_id>() - }); + +[](const bool rw, const type_info **buffer, const std::size_t length) { return rw ? fill_dependencies(typename resource_type::rw{}, buffer, length) : fill_dependencies(typename resource_type::ro{}, buffer, length); }, + +[](registry_type ®) { void(to_args(reg, typename resource_type::args{})); }, + &type_id>()}; + + track_dependencies(vertices.size(), requires_registry, typename resource_type::ro{}, typename resource_type::rw{}); + vertices.push_back(std::move(vdata)); } /** @@ -406,30 +325,26 @@ public: */ template void emplace(Type &value_or_instance, const char *name = nullptr) { - using resource_type = decltype(internal::constrained_function_to_resource(Candidate)); - constexpr auto requires_registry = type_list_contains_v>; + using resource_type = decltype(internal::constrained_function_to_resource_traits(Candidate)); + constexpr auto requires_registry = type_list_contains_v; - callback_type *callback = +[](const void *payload, basic_registry ®) { + callback_type *callback = +[](const void *payload, registry_type ®) { Type *curr = static_cast(const_cast *>(payload)); std::apply(Candidate, std::tuple_cat(std::forward_as_tuple(*curr), to_args(reg, typename resource_type::args{}))); }; - track_dependencies(vertices.size(), requires_registry, typename resource_type::ro{}, typename resource_type::rw{}); - - vertices.push_back({ + vertex_data vdata{ resource_type::ro::size, resource_type::rw::size, name, &value_or_instance, callback, - +[](const bool rw, type_info *buffer, const std::size_t length) { - return rw ? fill_dependencies(typename resource_type::rw{}, buffer, length) : fill_dependencies(typename resource_type::ro{}, buffer, length); - }, - +[](basic_registry ®) { - void(to_args(reg, typename resource_type::args{})); - }, - type_id>() - }); + +[](const bool rw, const type_info **buffer, const std::size_t length) { return rw ? fill_dependencies(typename resource_type::rw{}, buffer, length) : fill_dependencies(typename resource_type::ro{}, buffer, length); }, + +[](registry_type ®) { void(to_args(reg, typename resource_type::args{})); }, + &type_id>()}; + + track_dependencies(vertices.size(), requires_registry, typename resource_type::ro{}, typename resource_type::rw{}); + vertices.push_back(std::move(vdata)); } /** @@ -442,21 +357,20 @@ public: */ template void emplace(function_type *func, const void *payload = nullptr, const char *name = nullptr) { - using resource_type = internal::resource, type_list>; + using resource_type = internal::resource_traits, type_list>; track_dependencies(vertices.size(), true, typename resource_type::ro{}, typename resource_type::rw{}); - vertices.push_back({ + vertex_data vdata{ resource_type::ro::size, resource_type::rw::size, name, payload, func, - +[](const bool rw, type_info *buffer, const std::size_t length) { - return rw ? fill_dependencies(typename resource_type::rw{}, buffer, length) : fill_dependencies(typename resource_type::ro{}, buffer, length); - }, + +[](const bool rw, const type_info **buffer, const std::size_t length) { return rw ? fill_dependencies(typename resource_type::rw{}, buffer, length) : fill_dependencies(typename resource_type::ro{}, buffer, length); }, nullptr, - type_info{} - }); + &type_id()}; + + vertices.push_back(std::move(vdata)); } /** @@ -464,28 +378,19 @@ public: * @return The adjacency list of the task graph. */ std::vector graph() { - const auto edges = adjacency_matrix(); - - // creates the adjacency list std::vector adjacency_list{}; adjacency_list.reserve(vertices.size()); + auto adjacency_matrix = builder.graph(); - for(std::size_t col{}, length = vertices.size(); col < length; ++col) { + for(auto curr: adjacency_matrix.vertices()) { + const auto iterable = adjacency_matrix.in_edges(curr); std::vector reachable{}; - const auto row = col * length; - bool is_top_level = true; - for(std::size_t next{}; next < length; ++next) { - if(edges[row + next]) { - reachable.push_back(next); - } + for(auto &&edge: adjacency_matrix.out_edges(curr)) { + reachable.push_back(edge.second); } - for(std::size_t next{}; next < length && is_top_level; ++next) { - is_top_level = !edges[next * length + col]; - } - - adjacency_list.emplace_back(is_top_level, vertices[col], std::move(reachable)); + adjacency_list.emplace_back(iterable.cbegin() == iterable.cend(), vertices[curr], std::move(reachable)); } return adjacency_list; @@ -493,17 +398,15 @@ public: /*! @brief Erases all elements from a container. */ void clear() { - dependencies.clear(); + builder.clear(); vertices.clear(); } private: - std::unordered_map>> dependencies; std::vector vertices; + flow builder; }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/entity/poly_storage.hpp b/LiteLoader/third-party/include/entt/entity/poly_storage.hpp index d2a948f..a3f04fe 100644 --- a/LiteLoader/third-party/include/entt/entity/poly_storage.hpp +++ b/LiteLoader/third-party/include/entt/entity/poly_storage.hpp @@ -4,9 +4,9 @@ #include #include -#include "third-party/include/entt/core/type_info.hpp" -#include "third-party/include/entt/core/type_traits.hpp" -#include "third-party/include/entt/poly/poly.hpp" +#include "../core/type_info.hpp" +#include "../core/type_traits.hpp" +#include "../poly/poly.hpp" #include "fwd.hpp" diff --git a/LiteLoader/third-party/include/entt/entity/registry.hpp b/LiteLoader/third-party/include/entt/entity/registry.hpp index 959238b..4841640 100644 --- a/LiteLoader/third-party/include/entt/entity/registry.hpp +++ b/LiteLoader/third-party/include/entt/entity/registry.hpp @@ -1,85 +1,294 @@ #ifndef ENTT_ENTITY_REGISTRY_HPP #define ENTT_ENTITY_REGISTRY_HPP - #include #include +#include #include #include #include #include #include #include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/algorithm.hpp" -#include "third-party/include/entt/core/any.hpp" -#include "third-party/include/entt/core/fwd.hpp" -#include "third-party/include/entt/core/type_info.hpp" -#include "third-party/include/entt/core/type_traits.hpp" +#include "../config/config.h" +#include "../container/dense_map.hpp" +#include "../core/algorithm.hpp" +#include "../core/any.hpp" +#include "../core/compressed_pair.hpp" +#include "../core/fwd.hpp" +#include "../core/iterator.hpp" +#include "../core/memory.hpp" +#include "../core/type_info.hpp" +#include "../core/type_traits.hpp" +#include "../core/utility.hpp" #include "component.hpp" #include "entity.hpp" #include "fwd.hpp" #include "group.hpp" -#include "poly_storage.hpp" -#include "runtime_view.hpp" #include "sparse_set.hpp" #include "storage.hpp" -#include "utility.hpp" #include "view.hpp" - namespace entt { +/** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + +namespace internal { + +template +class registry_storage_iterator final { + template + friend class registry_storage_iterator; + + using mapped_type = std::remove_reference_t()->second)>; + +public: + using value_type = std::pair &>; + using pointer = input_iterator_pointer; + using reference = value_type; + using difference_type = std::ptrdiff_t; + using iterator_category = std::input_iterator_tag; + + constexpr registry_storage_iterator() noexcept + : it{} {} + + constexpr registry_storage_iterator(It iter) noexcept + : it{iter} {} + + template && std::is_constructible_v>> + constexpr registry_storage_iterator(const registry_storage_iterator &other) noexcept + : registry_storage_iterator{other.it} {} + + constexpr registry_storage_iterator &operator++() noexcept { + return ++it, *this; + } + + constexpr registry_storage_iterator operator++(int) noexcept { + registry_storage_iterator orig = *this; + return ++(*this), orig; + } + + constexpr registry_storage_iterator &operator--() noexcept { + return --it, *this; + } + + constexpr registry_storage_iterator operator--(int) noexcept { + registry_storage_iterator orig = *this; + return operator--(), orig; + } + + constexpr registry_storage_iterator &operator+=(const difference_type value) noexcept { + it += value; + return *this; + } + + constexpr registry_storage_iterator operator+(const difference_type value) const noexcept { + registry_storage_iterator copy = *this; + return (copy += value); + } + + constexpr registry_storage_iterator &operator-=(const difference_type value) noexcept { + return (*this += -value); + } + + constexpr registry_storage_iterator operator-(const difference_type value) const noexcept { + return (*this + -value); + } + + [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept { + return {it[value].first, *it[value].second}; + } + + [[nodiscard]] constexpr reference operator*() const noexcept { + return {it->first, *it->second}; + } + + [[nodiscard]] constexpr pointer operator->() const noexcept { + return operator*(); + } + + template + friend constexpr std::ptrdiff_t operator-(const registry_storage_iterator &, const registry_storage_iterator &) noexcept; + + template + friend constexpr bool operator==(const registry_storage_iterator &, const registry_storage_iterator &) noexcept; + + template + friend constexpr bool operator<(const registry_storage_iterator &, const registry_storage_iterator &) noexcept; + +private: + It it; +}; + +template +[[nodiscard]] constexpr std::ptrdiff_t operator-(const registry_storage_iterator &lhs, const registry_storage_iterator &rhs) noexcept { + return lhs.it - rhs.it; +} + +template +[[nodiscard]] constexpr bool operator==(const registry_storage_iterator &lhs, const registry_storage_iterator &rhs) noexcept { + return lhs.it == rhs.it; +} + +template +[[nodiscard]] constexpr bool operator!=(const registry_storage_iterator &lhs, const registry_storage_iterator &rhs) noexcept { + return !(lhs == rhs); +} + +template +[[nodiscard]] constexpr bool operator<(const registry_storage_iterator &lhs, const registry_storage_iterator &rhs) noexcept { + return lhs.it < rhs.it; +} + +template +[[nodiscard]] constexpr bool operator>(const registry_storage_iterator &lhs, const registry_storage_iterator &rhs) noexcept { + return rhs < lhs; +} + +template +[[nodiscard]] constexpr bool operator<=(const registry_storage_iterator &lhs, const registry_storage_iterator &rhs) noexcept { + return !(lhs > rhs); +} + +template +[[nodiscard]] constexpr bool operator>=(const registry_storage_iterator &lhs, const registry_storage_iterator &rhs) noexcept { + return !(lhs < rhs); +} + +class registry_context { + using key_type = id_type; + using mapped_type = basic_any<0u>; + using container_type = dense_map; + +public: + template + [[deprecated("Use ::emplace_as instead")]] Type &emplace_hint(const id_type id, Args &&...args) { + return emplace_as(id, std::forward(args)...); + } + + template + Type &emplace_as(const id_type id, Args &&...args) { + return any_cast(ctx.try_emplace(id, std::in_place_type, std::forward(args)...).first->second); + } + + template + Type &emplace(Args &&...args) { + return emplace_as(type_id().hash(), std::forward(args)...); + } + + template + Type &insert_or_assign(const id_type id, Type &&value) { + return any_cast> &>(ctx.insert_or_assign(id, std::forward(value)).first->second); + } + + template + Type &insert_or_assign(Type &&value) { + return insert_or_assign(type_id().hash(), std::forward(value)); + } + + template + bool erase(const id_type id = type_id().hash()) { + const auto it = ctx.find(id); + return it != ctx.end() && it->second.type() == type_id() ? (ctx.erase(it), true) : false; + } + + template + [[deprecated("Use ::get instead")]] [[nodiscard]] const Type &at(const id_type id = type_id().hash()) const { + return get(id); + } + + template + [[deprecated("Use ::get instead")]] [[nodiscard]] Type &at(const id_type id = type_id().hash()) { + return get(id); + } + + template + [[nodiscard]] const Type &get(const id_type id = type_id().hash()) const { + return any_cast(ctx.at(id)); + } + + template + [[nodiscard]] Type &get(const id_type id = type_id().hash()) { + return any_cast(ctx.at(id)); + } + + template + [[nodiscard]] const Type *find(const id_type id = type_id().hash()) const { + const auto it = ctx.find(id); + return it != ctx.cend() ? any_cast(&it->second) : nullptr; + } + + template + [[nodiscard]] Type *find(const id_type id = type_id().hash()) { + const auto it = ctx.find(id); + return it != ctx.end() ? any_cast(&it->second) : nullptr; + } + + template + [[nodiscard]] bool contains(const id_type id = type_id().hash()) const { + const auto it = ctx.find(id); + return it != ctx.cend() && it->second.type() == type_id(); + } + +private: + container_type ctx; +}; + +} // namespace internal + +/** + * Internal details not to be documented. + * @endcond + */ /** * @brief Fast and reliable entity-component system. - * - * The registry is the core class of the entity-component framework.
- * It stores entities and arranges pools of components on a per request basis. - * By means of a registry, users can manage entities and components, then create - * views or groups to iterate them. - * * @tparam Entity A valid entity type (see entt_traits for more details). + * @tparam Allocator Type of allocator used to manage memory and elements. */ -template +template class basic_registry { - using traits_type = entt_traits; - using poly_storage_type = typename poly_storage_traits::storage_type; - using basic_common_type = basic_sparse_set; + using alloc_traits = typename std::allocator_traits; + static_assert(std::is_same_v, "Invalid value type"); + using basic_common_type = basic_sparse_set; + using entity_traits = entt_traits; - template - using storage_type = constness_as_t>::storage_type, Component>; - - struct pool_data { - poly_storage_type poly; - std::unique_ptr pool{}; - }; + template + using storage_for_type = typename storage_for>>::type; template struct group_handler; template struct group_handler, get_t, Owned...> { - static_assert(!std::disjunction_v::in_place_delete...>, "Groups do not support in-place delete"); - static_assert(std::conjunction_v>..., std::is_same>..., std::is_same>...>, "One or more component types are invalid"); - std::conditional_t current{}; + // nasty workaround for an issue with the toolset v141 that doesn't accept a fold expression here + static_assert(!std::disjunction_v::in_place_delete>...>, "Groups do not support in-place delete"); + using value_type = std::conditional_t; + value_type current{}; - template + template + group_handler(Args &&...args) + : current{std::forward(args)...} {} + + template void maybe_valid_if(basic_registry &owner, const Entity entt) { - [[maybe_unused]] const auto cpools = std::make_tuple(owner.assure()...); + [[maybe_unused]] const auto cpools = std::forward_as_tuple(owner.assure()...); - const auto is_valid = ((std::is_same_v || std::get *>(cpools)->contains(entt)) && ...) - && ((std::is_same_v || owner.assure()->contains(entt)) && ...) - && ((std::is_same_v || !owner.assure()->contains(entt)) && ...); + const auto is_valid = ((std::is_same_v || std::get &>(cpools).contains(entt)) && ...) + && ((std::is_same_v || owner.assure().contains(entt)) && ...) + && ((std::is_same_v || !owner.assure().contains(entt)) && ...); if constexpr(sizeof...(Owned) == 0) { if(is_valid && !current.contains(entt)) { current.emplace(entt); } } else { - if(is_valid && !(std::get<0>(cpools)->index(entt) < current)) { + if(is_valid && !(std::get<0>(cpools).index(entt) < current)) { const auto pos = current++; - (std::get *>(cpools)->swap(std::get *>(cpools)->data()[pos], entt), ...); + (std::get &>(cpools).swap_elements(std::get &>(cpools).data()[pos], entt), ...); } } } @@ -88,9 +297,9 @@ class basic_registry { if constexpr(sizeof...(Owned) == 0) { current.remove(entt); } else { - if(const auto cpools = std::make_tuple(owner.assure()...); std::get<0>(cpools)->contains(entt) && (std::get<0>(cpools)->index(entt) < current)) { + if(const auto cpools = std::forward_as_tuple(owner.assure()...); std::get<0>(cpools).contains(entt) && (std::get<0>(cpools).index(entt) < current)) { const auto pos = --current; - (std::get *>(cpools)->swap(std::get *>(cpools)->data()[pos], entt), ...); + (std::get &>(cpools).swap_elements(std::get &>(cpools).data()[pos], entt), ...); } } } @@ -98,136 +307,226 @@ class basic_registry { struct group_data { std::size_t size; - std::unique_ptr group; - bool (* owned)(const id_type) ENTT_NOEXCEPT; - bool (* get)(const id_type) ENTT_NOEXCEPT; - bool (* exclude)(const id_type) ENTT_NOEXCEPT; + std::shared_ptr group; + bool (*owned)(const id_type) noexcept; + bool (*get)(const id_type) noexcept; + bool (*exclude)(const id_type) noexcept; }; - template - [[nodiscard]] storage_type * assure() const { - static_assert(std::is_same_v>, "Non-decayed types not allowed"); - const auto index = type_seq::value(); + template + [[nodiscard]] auto &assure(const id_type id = type_hash::value()) { + static_assert(std::is_same_v>, "Non-decayed types not allowed"); + auto &cpool = pools[id]; - if(!(index < pools.size())) { - pools.resize(size_type(index)+1u); + if(!cpool) { + cpool = std::allocate_shared>>(get_allocator(), get_allocator()); + cpool->bind(forward_as_any(*this)); } - if(auto &&pdata = pools[index]; !pdata.pool) { - pdata.pool.reset(new storage_type()); - pdata.poly.template emplace &>(*static_cast *>(pdata.pool.get())); + ENTT_ASSERT(cpool->type() == type_id(), "Unexpected type"); + return static_cast &>(*cpool); + } + + template + [[nodiscard]] const auto &assure(const id_type id = type_hash::value()) const { + static_assert(std::is_same_v>, "Non-decayed types not allowed"); + + if(const auto it = pools.find(id); it != pools.cend()) { + ENTT_ASSERT(it->second->type() == type_id(), "Unexpected type"); + return static_cast &>(*it->second); } - return static_cast *>(pools[index].pool.get()); + static storage_for_type placeholder{}; + return placeholder; } - template - [[nodiscard]] const storage_type * pool_if_exists() const ENTT_NOEXCEPT { - static_assert(std::is_same_v>, "Non-decayed types not allowed"); - const auto index = type_seq::value(); - return (!(index < pools.size()) || !pools[index].pool) ? nullptr : static_cast *>(pools[index].pool.get()); + auto generate_identifier(const std::size_t pos) noexcept { + ENTT_ASSERT(pos < entity_traits::to_entity(null), "No entities available"); + return entity_traits::combine(static_cast(pos), {}); } - auto generate_identifier(const std::size_t pos) ENTT_NOEXCEPT { - ENTT_ASSERT(pos < traits_type::to_integral(null), "No entities available"); - return traits_type::construct(static_cast(pos), {}); - } - - auto recycle_identifier() ENTT_NOEXCEPT { + auto recycle_identifier() noexcept { ENTT_ASSERT(free_list != null, "No entities available"); - const auto curr = traits_type::to_entity(free_list); - free_list = (tombstone | entities[curr]); - return (entities[curr] = traits_type::construct(curr, traits_type::to_version(entities[curr]))); + const auto curr = entity_traits::to_entity(free_list); + free_list = entity_traits::combine(entity_traits::to_integral(epool[curr]), tombstone); + return (epool[curr] = entity_traits::combine(curr, entity_traits::to_integral(epool[curr]))); } - auto release_entity(const Entity entity, const typename traits_type::version_type version) { - const typename traits_type::version_type vers = version + (version == traits_type::to_version(tombstone)); - entities[traits_type::to_entity(entity)] = traits_type::construct(traits_type::to_entity(free_list), vers); - free_list = (tombstone | entity); + auto release_entity(const Entity entt, const typename entity_traits::version_type version) { + const typename entity_traits::version_type vers = version + (version == entity_traits::to_version(tombstone)); + epool[entity_traits::to_entity(entt)] = entity_traits::construct(entity_traits::to_integral(free_list), vers); + free_list = entity_traits::combine(entity_traits::to_integral(entt), tombstone); return vers; } + void rebind() { + for(auto &&curr: pools) { + curr.second->bind(forward_as_any(*this)); + } + } + public: + /*! @brief Allocator type. */ + using allocator_type = Allocator; /*! @brief Underlying entity identifier. */ using entity_type = Entity; /*! @brief Underlying version type. */ - using version_type = typename traits_type::version_type; + using version_type = typename entity_traits::version_type; /*! @brief Unsigned integer type. */ using size_type = std::size_t; - /*! @brief Poly storage type. */ - using poly_storage = typename poly_storage_traits::storage_type; - - /** - * @brief Returns the entity identifier without the version. - * @param entity An entity identifier, either valid or not. - * @return The entity identifier without the version. - */ - [[nodiscard]] static entity_type entity(const entity_type entity) ENTT_NOEXCEPT { - return traits_type::construct(traits_type::to_entity(entity), {}); - } - - /** - * @brief Returns the version stored along with an entity identifier. - * @param entity An entity identifier, either valid or not. - * @return The version stored along with the given entity identifier. - */ - [[nodiscard]] static version_type version(const entity_type entity) ENTT_NOEXCEPT { - return traits_type::to_version(entity); - } + /*! @brief Common type among all storage types. */ + using base_type = basic_common_type; + /*! @brief Context type. */ + using context = internal::registry_context; /*! @brief Default constructor. */ - basic_registry() = default; - - /*! @brief Default move constructor. */ - basic_registry(basic_registry &&) = default; - - /*! @brief Default move assignment operator. @return This registry. */ - basic_registry & operator=(basic_registry &&) = default; + basic_registry() + : basic_registry{allocator_type{}} {} /** - * @brief Prepares a pool for the given type if required. - * @tparam Component Type of component for which to prepare a pool. + * @brief Constructs an empty registry with a given allocator. + * @param allocator The allocator to use. */ - template - void prepare() { - // suppress the warning due to the [[nodiscard]] attribute - static_cast(assure()); + explicit basic_registry(const allocator_type &allocator) + : basic_registry{0u, allocator} {} + + /** + * @brief Allocates enough memory upon construction to store `count` pools. + * @param count The number of pools to allocate memory for. + * @param allocator The allocator to use. + */ + basic_registry(const size_type count, const allocator_type &allocator = allocator_type{}) + : vars{}, + free_list{tombstone}, + epool{allocator}, + pools{allocator}, + groups{allocator} { + pools.reserve(count); } /** - * @brief Returns a poly storage for a given type. - * @param info The type for which to return a poly storage. - * @return A valid poly storage if a pool for the given type exists, an - * empty and thus invalid element otherwise. + * @brief Move constructor. + * @param other The instance to move from. */ - poly_storage & storage(const type_info info) { - ENTT_ASSERT(info.seq() < pools.size() && pools[info.seq()].poly, "Storage not available"); - return pools[info.seq()].poly; + basic_registry(basic_registry &&other) noexcept + : vars{std::move(other.vars)}, + free_list{std::move(other.free_list)}, + epool{std::move(other.epool)}, + pools{std::move(other.pools)}, + groups{std::move(other.groups)} { + rebind(); + } + + /** + * @brief Move assignment operator. + * @param other The instance to move from. + * @return This registry. + */ + basic_registry &operator=(basic_registry &&other) noexcept { + vars = std::move(other.vars); + free_list = std::move(other.free_list); + epool = std::move(other.epool); + pools = std::move(other.pools); + groups = std::move(other.groups); + + rebind(); + + return *this; + } + + /** + * @brief Exchanges the contents with those of a given registry. + * @param other Registry to exchange the content with. + */ + void swap(basic_registry &other) { + using std::swap; + swap(vars, other.vars); + swap(free_list, other.free_list); + swap(epool, other.epool); + swap(pools, other.pools); + swap(groups, other.groups); + + rebind(); + other.rebind(); + } + + /** + * @brief Returns the associated allocator. + * @return The associated allocator. + */ + [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { + return epool.get_allocator(); + } + + /** + * @brief Returns an iterable object to use to _visit_ a registry. + * + * The iterable object returns a pair that contains the name and a reference + * to the current storage. + * + * @return An iterable object to use to _visit_ the registry. + */ + [[nodiscard]] auto storage() noexcept { + return iterable_adaptor{internal::registry_storage_iterator{pools.begin()}, internal::registry_storage_iterator{pools.end()}}; } /*! @copydoc storage */ - const poly_storage & storage(const type_info info) const { - ENTT_ASSERT(info.seq() < pools.size() && pools[info.seq()].poly, "Storage not available"); - return pools[info.seq()].poly; + [[nodiscard]] auto storage() const noexcept { + return iterable_adaptor{internal::registry_storage_iterator{pools.cbegin()}, internal::registry_storage_iterator{pools.cend()}}; } /** - * @brief Returns the number of existing components of the given type. - * @tparam Component Type of component of which to return the size. - * @return Number of existing components of the given type. + * @brief Finds the storage associated with a given name, if any. + * @param id Name used to map the storage within the registry. + * @return A pointer to the storage if it exists, a null pointer otherwise. */ - template - [[nodiscard]] size_type size() const { - const auto *cpool = pool_if_exists(); - return cpool ? cpool->size() : size_type{}; + [[nodiscard]] base_type *storage(const id_type id) { + return const_cast(std::as_const(*this).storage(id)); + } + + /** + * @brief Finds the storage associated with a given name, if any. + * @param id Name used to map the storage within the registry. + * @return A pointer to the storage if it exists, a null pointer otherwise. + */ + [[nodiscard]] const base_type *storage(const id_type id) const { + const auto it = pools.find(id); + return it == pools.cend() ? nullptr : it->second.get(); + } + + /** + * @brief Returns the storage for a given component type. + * @tparam Type Type of component of which to return the storage. + * @param id Optional name used to map the storage within the registry. + * @return The storage for the given component type. + */ + template + decltype(auto) storage(const id_type id = type_hash::value()) { + return assure(id); + } + + /** + * @brief Returns the storage for a given component type. + * + * @warning + * If a storage for the given component doesn't exist yet, a temporary + * placeholder is returned instead. + * + * @tparam Type Type of component of which to return the storage. + * @param id Optional name used to map the storage within the registry. + * @return The storage for the given component type. + */ + template + decltype(auto) storage(const id_type id = type_hash::value()) const { + return assure(id); } /** * @brief Returns the number of entities created so far. * @return Number of entities created so far. */ - [[nodiscard]] size_type size() const ENTT_NOEXCEPT { - return entities.size(); + [[nodiscard]] size_type size() const noexcept { + return epool.size(); } /** @@ -235,55 +534,21 @@ public: * @return Number of entities still in use. */ [[nodiscard]] size_type alive() const { - auto sz = entities.size(); + auto sz = epool.size(); for(auto curr = free_list; curr != null; --sz) { - curr = entities[traits_type::to_entity(curr)]; + curr = epool[entity_traits::to_entity(curr)]; } return sz; } /** - * @brief Increases the capacity of the registry or of the pools for the - * given components. - * - * If no components are specified, the capacity of the registry is - * increased, that is the number of entities it contains. Otherwise the - * capacity of the pools for the given components is increased.
- * In both cases, if the new capacity is greater than the current capacity, - * new storage is allocated, otherwise the method does nothing. - * - * @tparam Component Types of components for which to reserve storage. + * @brief Increases the capacity (number of entities) of the registry. * @param cap Desired capacity. */ - template void reserve(const size_type cap) { - if constexpr(sizeof...(Component) == 0) { - entities.reserve(cap); - } else { - (assure()->reserve(cap), ...); - } - } - - /** - * @brief Reserves enough space to store `count` pools. - * @param count Number of pools to reserve space for. - */ - [[deprecated("No longer supported")]] - void reserve_pools(const size_t count) { - pools.reserve(count); - } - - /** - * @brief Returns the capacity of the pool for the given component. - * @tparam Component Type of component in which one is interested. - * @return Capacity of the pool of the given component. - */ - template - [[nodiscard]] size_type capacity() const { - const auto *cpool = pool_if_exists(); - return cpool ? cpool->capacity() : size_type{}; + epool.reserve(cap); } /** @@ -291,45 +556,23 @@ public: * allocated space for. * @return Capacity of the registry. */ - [[nodiscard]] size_type capacity() const ENTT_NOEXCEPT { - return entities.capacity(); + [[nodiscard]] size_type capacity() const noexcept { + return epool.capacity(); } /** - * @brief Requests the removal of unused capacity for the given components. - * @tparam Component Types of components for which to reclaim unused - * capacity. + * @brief Checks whether the registry is empty (no entities still in use). + * @return True if the registry is empty, false otherwise. */ - template - void shrink_to_fit() { - (assure()->shrink_to_fit(), ...); - } - - /** - * @brief Checks whether the registry or the pools of the given components - * are empty. - * - * A registry is considered empty when it doesn't contain entities that are - * still in use. - * - * @tparam Component Types of components in which one is interested. - * @return True if the registry or the pools of the given components are - * empty, false otherwise. - */ - template [[nodiscard]] bool empty() const { - if constexpr(sizeof...(Component) == 0) { - return !alive(); - } else { - return [](const auto *... cpool) { return ((!cpool || cpool->empty()) && ...); }(pool_if_exists()...); - } + return !alive(); } /** * @brief Direct access to the list of entities of a registry. * * The returned pointer is such that range `[data(), data() + size())` is - * always a valid range, even if the container is empty. + * always a valid range, even if the registry is empty. * * @warning * This list contains both valid and destroyed entities and isn't suitable @@ -337,8 +580,8 @@ public: * * @return A pointer to the array of entities. */ - [[nodiscard]] const entity_type * data() const ENTT_NOEXCEPT { - return entities.data(); + [[nodiscard]] const entity_type *data() const noexcept { + return epool.data(); } /** @@ -349,93 +592,73 @@ public: * * @return The head of the list of released entities. */ - [[nodiscard]] entity_type released() const ENTT_NOEXCEPT { + [[nodiscard]] entity_type released() const noexcept { return free_list; } - /*! @copydoc released */ - [[deprecated("Use ::released instead")]] - [[nodiscard]] entity_type destroyed() const ENTT_NOEXCEPT { - return released(); - } - /** - * @brief Checks if an entity identifier refers to a valid entity. - * @param entity An entity identifier, either valid or not. + * @brief Checks if an identifier refers to a valid entity. + * @param entt An identifier, either valid or not. * @return True if the identifier is valid, false otherwise. */ - [[nodiscard]] bool valid(const entity_type entity) const { - const auto pos = size_type(traits_type::to_entity(entity)); - return (pos < entities.size() && entities[pos] == entity); + [[nodiscard]] bool valid(const entity_type entt) const { + const auto pos = size_type(entity_traits::to_entity(entt)); + return (pos < epool.size() && epool[pos] == entt); } /** - * @brief Returns the actual version for an entity identifier. - * - * @warning - * Attempting to use an entity that doesn't belong to the registry results - * in undefined behavior. An entity belongs to the registry even if it has - * been previously destroyed and/or recycled. - * - * @param entity A valid entity identifier. - * @return Actual version for the given entity identifier. + * @brief Returns the actual version for an identifier. + * @param entt A valid identifier. + * @return The version for the given identifier if valid, the tombstone + * version otherwise. */ - [[nodiscard]] version_type current(const entity_type entity) const { - const auto pos = size_type(traits_type::to_entity(entity)); - ENTT_ASSERT(pos < entities.size(), "Entity does not exist"); - return version(entities[pos]); + [[nodiscard]] version_type current(const entity_type entt) const { + const auto pos = size_type(entity_traits::to_entity(entt)); + return entity_traits::to_version(pos < epool.size() ? epool[pos] : tombstone); } /** - * @brief Creates a new entity and returns it. - * - * There are two kinds of possible entity identifiers: - * - * * Newly created ones in case no entities have been previously destroyed. - * * Recycled ones with updated versions. - * - * @return A valid entity identifier. + * @brief Creates a new entity or recycles a destroyed one. + * @return A valid identifier. */ [[nodiscard]] entity_type create() { - return (free_list == null) ? entities.emplace_back(generate_identifier(entities.size())) : recycle_identifier(); + return (free_list == null) ? epool.emplace_back(generate_identifier(epool.size())) : recycle_identifier(); } /** - * @brief Creates a new entity and returns it. + * @copybrief create * - * @sa create + * If the requested entity isn't in use, the suggested identifier is used. + * Otherwise, a new identifier is generated. * - * If the requested entity isn't in use, the suggested identifier is created - * and returned. Otherwise, a new identifier is generated. - * - * @param hint Required entity identifier. - * @return A valid entity identifier. + * @param hint Required identifier. + * @return A valid identifier. */ [[nodiscard]] entity_type create(const entity_type hint) { - const auto length = entities.size(); + const auto length = epool.size(); if(hint == null || hint == tombstone) { return create(); - } else if(const auto req = traits_type::to_entity(hint); !(req < length)) { - entities.resize(size_type(req) + 1u, null); + } else if(const auto req = entity_traits::to_entity(hint); !(req < length)) { + epool.resize(size_type(req) + 1u, null); for(auto pos = length; pos < req; ++pos) { release_entity(generate_identifier(pos), {}); } - return (entities[req] = hint); - } else if(const auto curr = traits_type::to_entity(entities[req]); req == curr) { + return (epool[req] = hint); + } else if(const auto curr = entity_traits::to_entity(epool[req]); req == curr) { return create(); } else { auto *it = &free_list; - for(; traits_type::to_entity(*it) != req; it = &entities[traits_type::to_entity(*it)]); - *it = traits_type::construct(curr, traits_type::to_version(*it)); - return (entities[req] = hint); + for(; entity_traits::to_entity(*it) != req; it = &epool[entity_traits::to_entity(*it)]) {} + *it = entity_traits::combine(curr, entity_traits::to_integral(*it)); + return (epool[req] = hint); } } /** - * @brief Assigns each element in a range an entity. + * @brief Assigns each element in a range an identifier. * * @sa create * @@ -449,19 +672,19 @@ public: *first = recycle_identifier(); } - const auto length = entities.size(); - entities.resize(length + std::distance(first, last), null); + const auto length = epool.size(); + epool.resize(length + std::distance(first, last), null); for(auto pos = length; first != last; ++first, ++pos) { - *first = entities[pos] = generate_identifier(pos); + *first = epool[pos] = generate_identifier(pos); } } /** - * @brief Assigns entities to an empty registry. + * @brief Assigns identifiers to an empty registry. * * This function is intended for use in conjunction with `data`, `size` and - * `destroyed`.
+ * `released`.
* Don't try to inject ranges of randomly generated entities nor the _wrong_ * head for the list of destroyed entities. There is no guarantee that a * registry will continue to work properly in this case. @@ -477,44 +700,45 @@ public: template void assign(It first, It last, const entity_type destroyed) { ENTT_ASSERT(!alive(), "Entities still alive"); - entities.assign(first, last); + epool.assign(first, last); free_list = destroyed; } /** - * @brief Releases an entity identifier. + * @brief Releases an identifier. * * The version is updated and the identifier can be recycled at any time. * * @warning * Attempting to use an invalid entity results in undefined behavior. * - * @param entity A valid entity identifier. + * @param entt A valid identifier. * @return The version of the recycled entity. */ - version_type release(const entity_type entity) { - return release(entity, version(entity) + 1u); + version_type release(const entity_type entt) { + return release(entt, static_cast(entity_traits::to_version(entt) + 1u)); } /** - * @brief Releases an entity identifier. + * @brief Releases an identifier. * * The suggested version or the valid version closest to the suggested one * is used instead of the implicitly generated version. * * @sa release * - * @param entity A valid entity identifier. + * @param entt A valid identifier. * @param version A desired version upon destruction. * @return The version actually assigned to the entity. */ - version_type release(const entity_type entity, const version_type version) { - ENTT_ASSERT(orphan(entity), "Non-orphan entity"); - return release_entity(entity, version); + version_type release(const entity_type entt, const version_type version) { + ENTT_ASSERT(valid(entt), "Invalid identifier"); + ENTT_ASSERT(std::all_of(pools.cbegin(), pools.cend(), [entt](auto &&curr) { return (curr.second->current(entt) == entity_traits::to_version(tombstone)); }), "Non-orphan entity"); + return release_entity(entt, version); } /** - * @brief Releases all entity identifiers in a range. + * @brief Releases all identifiers in a range. * * @sa release * @@ -525,27 +749,25 @@ public: template void release(It first, It last) { for(; first != last; ++first) { - release(*first, version(*first) + 1u); + release(*first); } } /** * @brief Destroys an entity and releases its identifier. * - * The version is updated and the identifier can be recycled at any time. + * @sa release * * @warning * Adding or removing components to an entity that is being destroyed can - * result in undefined behavior. + * result in undefined behavior. Attempting to use an invalid entity results + * in undefined behavior. * - * @warning - * Attempting to use an invalid entity results in undefined behavior. - * - * @param entity A valid entity identifier. + * @param entt A valid identifier. * @return The version of the recycled entity. */ - version_type destroy(const entity_type entity) { - return destroy(entity, version(entity) + 1u); + version_type destroy(const entity_type entt) { + return destroy(entt, static_cast(entity_traits::to_version(entt) + 1u)); } /** @@ -556,18 +778,16 @@ public: * * @sa destroy * - * @param entity A valid entity identifier. + * @param entt A valid identifier. * @param version A desired version upon destruction. * @return The version actually assigned to the entity. */ - version_type destroy(const entity_type entity, const version_type version) { - ENTT_ASSERT(valid(entity), "Invalid entity"); - - for(auto &&pdata: pools) { - pdata.pool && pdata.pool->remove(entity, this); + version_type destroy(const entity_type entt, const version_type version) { + for(size_type pos = pools.size(); pos; --pos) { + pools.begin()[pos - 1u].second->remove(entt); } - return release_entity(entity, version); + return release(entt, version); } /** @@ -581,40 +801,29 @@ public: */ template void destroy(It first, It last) { - if constexpr(is_iterator_type_v) { - for(; first != last; ++first) { - destroy(*first, version(*first) + 1u); - } - } else { - for(auto &&pdata: pools) { - pdata.pool && pdata.pool->remove(first, last, this); - } - - release(first, last); + for(; first != last; ++first) { + destroy(*first); } } /** * @brief Assigns the given component to an entity. * - * A new instance of the given component is created and initialized with the - * arguments provided (the component must have a proper constructor or be of - * aggregate type). Then the component is assigned to the given entity. + * The component must have a proper constructor or be of aggregate type. * * @warning - * Attempting to use an invalid entity or to assign a component to an entity - * that already owns it results in undefined behavior. + * Attempting to assign a component to an entity that already owns it + * results in undefined behavior. * - * @tparam Component Type of component to create. + * @tparam Type Type of component to create. * @tparam Args Types of arguments to use to construct the component. - * @param entity A valid entity identifier. + * @param entt A valid identifier. * @param args Parameters to use to initialize the component. * @return A reference to the newly created component. */ - template - decltype(auto) emplace(const entity_type entity, Args &&... args) { - ENTT_ASSERT(valid(entity), "Invalid entity"); - return assure()->emplace(*this, entity, std::forward(args)...); + template + decltype(auto) emplace(const entity_type entt, Args &&...args) { + return assure().emplace(entt, std::forward(args)...); } /** @@ -622,16 +831,15 @@ public: * * @sa emplace * - * @tparam Component Type of component to create. + * @tparam Type Type of component to create. * @tparam It Type of input iterator. * @param first An iterator to the first element of the range of entities. * @param last An iterator past the last element of the range of entities. * @param value An instance of the component to assign. */ - template - void insert(It first, It last, const Component &value = {}) { - ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }), "Invalid entity"); - assure()->insert(*this, first, last, value); + template + void insert(It first, It last, const Type &value = {}) { + assure().insert(first, last, value); } /** @@ -639,57 +847,46 @@ public: * * @sa emplace * - * @tparam Component Type of component to create. + * @tparam Type Type of component to create. * @tparam EIt Type of input iterator. * @tparam CIt Type of input iterator. * @param first An iterator to the first element of the range of entities. * @param last An iterator past the last element of the range of entities. * @param from An iterator to the first element of the range of components. */ - template::value_type>, Component>>> + template::value_type, Type>>> void insert(EIt first, EIt last, CIt from) { - static_assert(std::is_constructible_v::value_type>, "Invalid value type"); - ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }), "Invalid entity"); - assure()->insert(*this, first, last, from); + assure().insert(first, last, from); } /** * @brief Assigns or replaces the given component for an entity. * - * Equivalent to the following snippet (pseudocode): + * @sa emplace + * @sa replace * - * @code{.cpp} - * auto &component = registry.all_of(entity) ? registry.replace(entity, args...) : registry.emplace(entity, args...); - * @endcode - * - * Prefer this function anyway because it has slightly better performance. - * - * @warning - * Attempting to use an invalid entity results in undefined behavior. - * - * @tparam Component Type of component to assign or replace. + * @tparam Type Type of component to assign or replace. * @tparam Args Types of arguments to use to construct the component. - * @param entity A valid entity identifier. + * @param entt A valid identifier. * @param args Parameters to use to initialize the component. * @return A reference to the newly created component. */ - template - decltype(auto) emplace_or_replace(const entity_type entity, Args &&... args) { - ENTT_ASSERT(valid(entity), "Invalid entity"); - auto *cpool = assure(); - - return cpool->contains(entity) - ? cpool->patch(*this, entity, [&args...](auto &... curr) { ((curr = Component{std::forward(args)...}), ...); }) - : cpool->emplace(*this, entity, std::forward(args)...); + template + decltype(auto) emplace_or_replace(const entity_type entt, Args &&...args) { + if(auto &cpool = assure(); cpool.contains(entt)) { + return cpool.patch(entt, [&args...](auto &...curr) { ((curr = Type{std::forward(args)...}), ...); }); + } else { + return cpool.emplace(entt, std::forward(args)...); + } } /** * @brief Patches the given component for an entity. * - * The signature of the functions should be equivalent to the following: + * The signature of the function should be equivalent to the following: * * @code{.cpp} - * void(Component &); + * void(Type &); * @endcode * * @note @@ -698,58 +895,51 @@ public: * for them. * * @warning - * Attempting to use an invalid entity or to patch a component of an entity - * that doesn't own it results in undefined behavior. + * Attempting to to patch a component of an entity that doesn't own it + * results in undefined behavior. * - * @tparam Component Type of component to patch. + * @tparam Type Type of component to patch. * @tparam Func Types of the function objects to invoke. - * @param entity A valid entity identifier. + * @param entt A valid identifier. * @param func Valid function objects. * @return A reference to the patched component. */ - template - decltype(auto) patch(const entity_type entity, Func &&... func) { - ENTT_ASSERT(valid(entity), "Invalid entity"); - return assure()->patch(*this, entity, std::forward(func)...); + template + decltype(auto) patch(const entity_type entt, Func &&...func) { + return assure().patch(entt, std::forward(func)...); } /** * @brief Replaces the given component for an entity. * - * A new instance of the given component is created and initialized with the - * arguments provided (the component must have a proper constructor or be of - * aggregate type). Then the component is assigned to the given entity. + * The component must have a proper constructor or be of aggregate type. * * @warning - * Attempting to use an invalid entity or to replace a component of an - * entity that doesn't own it results in undefined behavior. + * Attempting to replace a component of an entity that doesn't own it + * results in undefined behavior. * - * @tparam Component Type of component to replace. + * @tparam Type Type of component to replace. * @tparam Args Types of arguments to use to construct the component. - * @param entity A valid entity identifier. + * @param entt A valid identifier. * @param args Parameters to use to initialize the component. * @return A reference to the component being replaced. */ - template - decltype(auto) replace(const entity_type entity, Args &&... args) { - return assure()->patch(*this, entity, [&args...](auto &... curr) { ((curr = Component{std::forward(args)...}), ...); }); + template + decltype(auto) replace(const entity_type entt, Args &&...args) { + return patch(entt, [&args...](auto &...curr) { ((curr = Type{std::forward(args)...}), ...); }); } /** * @brief Removes the given components from an entity. * - * @warning - * Attempting to use an invalid entity results in undefined behavior. - * - * @tparam Component Types of components to remove. - * @param entity A valid entity identifier. + * @tparam Type Type of component to remove. + * @tparam Other Other types of components to remove. + * @param entt A valid identifier. * @return The number of components actually removed. */ - template - size_type remove(const entity_type entity) { - ENTT_ASSERT(valid(entity), "Invalid entity"); - static_assert(sizeof...(Component) > 0, "Provide one or more component types"); - return (assure()->remove(entity, this) + ... + size_type{}); + template + size_type remove(const entity_type entt) { + return (assure().remove(entt) + ... + assure().remove(entt)); } /** @@ -757,42 +947,42 @@ public: * * @sa remove * - * @tparam Component Types of components to remove. + * @tparam Type Type of component to remove. + * @tparam Other Other types of components to remove. * @tparam It Type of input iterator. * @param first An iterator to the first element of the range of entities. * @param last An iterator past the last element of the range of entities. * @return The number of components actually removed. */ - template + template size_type remove(It first, It last) { - static_assert(sizeof...(Component) > 0, "Provide one or more component types"); - const auto cpools = std::make_tuple(assure()...); - size_type count{}; + if constexpr(sizeof...(Other) == 0u) { + return assure().remove(std::move(first), std::move(last)); + } else { + size_type count{}; - for(; first != last; ++first) { - const auto entity = *first; - ENTT_ASSERT(valid(entity), "Invalid entity"); - count += (std::get *>(cpools)->remove(entity, this) + ...); + for(auto cpools = std::forward_as_tuple(assure(), assure()...); first != last; ++first) { + count += std::apply([entt = *first](auto &...curr) { return (curr.remove(entt) + ... + 0u); }, cpools); + } + + return count; } - - return count; } /** * @brief Erases the given components from an entity. * * @warning - * Attempting to use an invalid entity or to erase a component from an - * entity that doesn't own it results in undefined behavior. + * Attempting to erase a component from an entity that doesn't own it + * results in undefined behavior. * - * @tparam Component Types of components to erase. - * @param entity A valid entity identifier. + * @tparam Type Types of components to erase. + * @tparam Other Other types of components to erase. + * @param entt A valid identifier. */ - template - void erase(const entity_type entity) { - ENTT_ASSERT(valid(entity), "Invalid entity"); - static_assert(sizeof...(Component) > 0, "Provide one or more component types"); - (assure()->erase(entity, this), ...); + template + void erase(const entity_type entt) { + (assure().erase(entt), (assure().erase(entt), ...)); } /** @@ -800,135 +990,89 @@ public: * * @sa erase * - * @tparam Component Types of components to erase. + * @tparam Type Types of components to erase. + * @tparam Other Other types of components to erase. * @tparam It Type of input iterator. * @param first An iterator to the first element of the range of entities. * @param last An iterator past the last element of the range of entities. */ - template + template void erase(It first, It last) { - static_assert(sizeof...(Component) > 0, "Provide one or more component types"); - const auto cpools = std::make_tuple(assure()...); - - for(; first != last; ++first) { - const auto entity = *first; - ENTT_ASSERT(valid(entity), "Invalid entity"); - (std::get *>(cpools)->erase(entity, this), ...); + if constexpr(sizeof...(Other) == 0u) { + assure().erase(std::move(first), std::move(last)); + } else { + for(auto cpools = std::forward_as_tuple(assure(), assure()...); first != last; ++first) { + std::apply([entt = *first](auto &...curr) { (curr.erase(entt), ...); }, cpools); + } } } /** * @brief Removes all tombstones from a registry or only the pools for the * given components. - * @tparam Component Types of components for which to clear all tombstones. + * @tparam Type Types of components for which to clear all tombstones. */ - template + template void compact() { - if constexpr(sizeof...(Component) == 0) { - for(auto &&pdata: pools) { - pdata.pool && (pdata.pool->compact(), true); + if constexpr(sizeof...(Type) == 0) { + for(auto &&curr: pools) { + curr.second->compact(); } } else { - (assure()->compact(), ...); - } - } - - /*! @copydoc remove */ - template - [[deprecated("Use ::remove instead")]] - size_type remove_if_exists(const entity_type entity) { - return remove(entity); - } - - /** - * @brief Removes all the components from an entity and makes it orphaned. - * - * @warning - * In case there are listeners that observe the destruction of components - * and assign other components to the entity in their bodies, the result of - * invoking this function may not be as expected. In the worst case, it - * could lead to undefined behavior. - * - * @warning - * Attempting to use an invalid entity results in undefined behavior. - * - * @param entity A valid entity identifier. - */ - [[deprecated("Use ::destroy(entity)/::create(entity) instead")]] - void remove_all(const entity_type entity) { - ENTT_ASSERT(valid(entity), "Invalid entity"); - - for(auto &&pdata: pools) { - pdata.pool && pdata.pool->remove(entity, this); + (assure().compact(), ...); } } /** - * @brief Checks if an entity has all the given components. - * - * @warning - * Attempting to use an invalid entity results in undefined behavior. - * - * @tparam Component Components for which to perform the check. - * @param entity A valid entity identifier. - * @return True if the entity has all the components, false otherwise. + * @brief Check if an entity is part of all the given storage. + * @tparam Type Type of storage to check for. + * @param entt A valid identifier. + * @return True if the entity is part of all the storage, false otherwise. */ - template - [[nodiscard]] bool all_of(const entity_type entity) const { - ENTT_ASSERT(valid(entity), "Invalid entity"); - return [entity](const auto *... cpool) { return ((cpool && cpool->contains(entity)) && ...); }(pool_if_exists()...); + template + [[nodiscard]] bool all_of(const entity_type entt) const { + return (assure>().contains(entt) && ...); } /** - * @brief Checks if an entity has at least one of the given components. - * - * @warning - * Attempting to use an invalid entity results in undefined behavior. - * - * @tparam Component Components for which to perform the check. - * @param entity A valid entity identifier. - * @return True if the entity has at least one of the given components, - * false otherwise. + * @brief Check if an entity is part of at least one given storage. + * @tparam Type Type of storage to check for. + * @param entt A valid identifier. + * @return True if the entity is part of at least one storage, false + * otherwise. */ - template - [[nodiscard]] bool any_of(const entity_type entity) const { - ENTT_ASSERT(valid(entity), "Invalid entity"); - return [entity](const auto *... cpool) { return !((!cpool || !cpool->contains(entity)) && ...); }(pool_if_exists()...); + template + [[nodiscard]] bool any_of(const entity_type entt) const { + return (assure>().contains(entt) || ...); } /** * @brief Returns references to the given components for an entity. * * @warning - * Attempting to use an invalid entity or to get a component from an entity - * that doesn't own it results in undefined behavior. + * Attempting to get a component from an entity that doesn't own it results + * in undefined behavior. * - * @tparam Component Types of components to get. - * @param entity A valid entity identifier. + * @tparam Type Types of components to get. + * @param entt A valid identifier. * @return References to the components owned by the entity. */ - template - [[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entity) const { - ENTT_ASSERT(valid(entity), "Invalid entity"); - - if constexpr(sizeof...(Component) == 1) { - const auto *cpool = pool_if_exists...>(); - ENTT_ASSERT(cpool, "Storage not available"); - return cpool->get(entity); + template + [[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entt) const { + if constexpr(sizeof...(Type) == 1u) { + return (assure>().get(entt), ...); } else { - return std::forward_as_tuple(get(entity)...); + return std::forward_as_tuple(get(entt)...); } } /*! @copydoc get */ - template - [[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entity) { - ENTT_ASSERT(valid(entity), "Invalid entity"); - - if constexpr(sizeof...(Component) == 1) { - return (const_cast(assure>()->get(entity)), ...); + template + [[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entt) { + if constexpr(sizeof...(Type) == 1u) { + return (const_cast(std::as_const(*this).template get(entt)), ...); } else { - return std::forward_as_tuple(get(entity)...); + return std::forward_as_tuple(get(entt)...); } } @@ -936,98 +1080,83 @@ public: * @brief Returns a reference to the given component for an entity. * * In case the entity doesn't own the component, the parameters provided are - * used to construct it.
- * Equivalent to the following snippet (pseudocode): + * used to construct it. * - * @code{.cpp} - * auto &component = registry.all_of(entity) ? registry.get(entity) : registry.emplace(entity, args...); - * @endcode + * @sa get + * @sa emplace * - * Prefer this function anyway because it has slightly better performance. - * - * @warning - * Attempting to use an invalid entity results in undefined behavior. - * - * @tparam Component Type of component to get. + * @tparam Type Type of component to get. * @tparam Args Types of arguments to use to construct the component. - * @param entity A valid entity identifier. + * @param entt A valid identifier. * @param args Parameters to use to initialize the component. * @return Reference to the component owned by the entity. */ - template - [[nodiscard]] decltype(auto) get_or_emplace(const entity_type entity, Args &&... args) { - ENTT_ASSERT(valid(entity), "Invalid entity"); - auto *cpool = assure(); - return cpool->contains(entity) ? cpool->get(entity) : cpool->emplace(*this, entity, std::forward(args)...); + template + [[nodiscard]] decltype(auto) get_or_emplace(const entity_type entt, Args &&...args) { + if(auto &cpool = assure(); cpool.contains(entt)) { + return cpool.get(entt); + } else { + return cpool.emplace(entt, std::forward(args)...); + } } /** * @brief Returns pointers to the given components for an entity. * - * @warning - * Attempting to use an invalid entity results in undefined behavior. - * * @note * The registry retains ownership of the pointed-to components. * - * @tparam Component Types of components to get. - * @param entity A valid entity identifier. + * @tparam Type Types of components to get. + * @param entt A valid identifier. * @return Pointers to the components owned by the entity. */ - template - [[nodiscard]] auto try_get([[maybe_unused]] const entity_type entity) const { - ENTT_ASSERT(valid(entity), "Invalid entity"); - - if constexpr(sizeof...(Component) == 1) { - const auto *cpool = pool_if_exists...>(); - return (cpool && cpool->contains(entity)) ? &cpool->get(entity) : nullptr; + template + [[nodiscard]] auto try_get([[maybe_unused]] const entity_type entt) const { + if constexpr(sizeof...(Type) == 1) { + const auto &cpool = assure...>(); + return cpool.contains(entt) ? std::addressof(cpool.get(entt)) : nullptr; } else { - return std::make_tuple(try_get(entity)...); + return std::make_tuple(try_get(entt)...); } } /*! @copydoc try_get */ - template - [[nodiscard]] auto try_get([[maybe_unused]] const entity_type entity) { - ENTT_ASSERT(valid(entity), "Invalid entity"); - - if constexpr(sizeof...(Component) == 1) { - return (const_cast(std::as_const(*this).template try_get(entity)), ...); + template + [[nodiscard]] auto try_get([[maybe_unused]] const entity_type entt) { + if constexpr(sizeof...(Type) == 1) { + return (const_cast(std::as_const(*this).template try_get(entt)), ...); } else { - return std::make_tuple(try_get(entity)...); + return std::make_tuple(try_get(entt)...); } } /** * @brief Clears a whole registry or the pools for the given components. - * @tparam Component Types of components to remove from their entities. + * @tparam Type Types of components to remove from their entities. */ - template + template void clear() { - if constexpr(sizeof...(Component) == 0) { - for(auto &&pdata: pools) { - pdata.pool && (pdata.pool->clear(this), true); + if constexpr(sizeof...(Type) == 0) { + for(auto &&curr: pools) { + curr.second->clear(); } - each([this](const auto entity) { release_entity(entity, version(entity) + 1u); }); + each([this](const auto entity) { this->release(entity); }); } else { - (assure()->clear(this), ...); + (assure().clear(), ...); } } /** * @brief Iterates all the entities that are still in use. * - * The function object is invoked for each entity that is still in use.
* The signature of the function should be equivalent to the following: * * @code{.cpp} * void(const Entity); * @endcode * - * This function is fairly slow and should not be used frequently. However, - * it's useful for iterating all the entities still in use, regardless of - * their components. + * It's not defined whether entities created during iteration are returned. * * @tparam Func Type of the function object to invoke. * @param func A valid function object. @@ -1035,12 +1164,12 @@ public: template void each(Func func) const { if(free_list == null) { - for(auto pos = entities.size(); pos; --pos) { - func(entities[pos-1]); + for(auto pos = epool.size(); pos; --pos) { + func(epool[pos - 1]); } } else { - for(auto pos = entities.size(); pos; --pos) { - if(const auto entity = entities[pos - 1]; traits_type::to_entity(entity) == (pos - 1)) { + for(auto pos = epool.size(); pos; --pos) { + if(const auto entity = epool[pos - 1]; entity_traits::to_entity(entity) == (pos - 1)) { func(entity); } } @@ -1049,258 +1178,160 @@ public: /** * @brief Checks if an entity has components assigned. - * @param entity A valid entity identifier. + * @param entt A valid identifier. * @return True if the entity has no components assigned, false otherwise. */ - [[nodiscard]] bool orphan(const entity_type entity) const { - ENTT_ASSERT(valid(entity), "Invalid entity"); - return std::none_of(pools.cbegin(), pools.cend(), [entity](auto &&pdata) { return pdata.pool && pdata.pool->contains(entity); }); - } - - /** - * @brief Iterates orphans and applies them the given function object. - * - * The function object is invoked for each entity that is still in use and - * has no components assigned.
- * The signature of the function should be equivalent to the following: - * - * @code{.cpp} - * void(const Entity); - * @endcode - * - * This function can be very slow and should not be used frequently. - * - * @tparam Func Type of the function object to invoke. - * @param func A valid function object. - */ - template - void orphans(Func func) const { - each([this, &func](const auto entity) { - if(orphan(entity)) { - func(entity); - } - }); + [[nodiscard]] bool orphan(const entity_type entt) const { + return std::none_of(pools.cbegin(), pools.cend(), [entt](auto &&curr) { return curr.second->contains(entt); }); } /** * @brief Returns a sink object for the given component. * - * The sink returned by this function can be used to receive notifications - * whenever a new instance of the given component is created and assigned to - * an entity.
+ * Use this function to receive notifications whenever a new instance of the + * given component is created and assigned to an entity.
* The function type for a listener is equivalent to: * * @code{.cpp} * void(basic_registry &, Entity); * @endcode * - * Listeners are invoked **after** the component has been assigned to the - * entity. + * Listeners are invoked **after** assigning the component to the entity. * * @sa sink * - * @tparam Component Type of component of which to get the sink. + * @tparam Type Type of component of which to get the sink. * @return A temporary sink object. */ - template + template [[nodiscard]] auto on_construct() { - return assure()->on_construct(); + return assure().on_construct(); } /** * @brief Returns a sink object for the given component. * - * The sink returned by this function can be used to receive notifications - * whenever an instance of the given component is explicitly updated.
+ * Use this function to receive notifications whenever an instance of the + * given component is explicitly updated.
* The function type for a listener is equivalent to: * * @code{.cpp} * void(basic_registry &, Entity); * @endcode * - * Listeners are invoked **after** the component has been updated. + * Listeners are invoked **after** updating the component. * * @sa sink * - * @tparam Component Type of component of which to get the sink. + * @tparam Type Type of component of which to get the sink. * @return A temporary sink object. */ - template + template [[nodiscard]] auto on_update() { - return assure()->on_update(); + return assure().on_update(); } /** * @brief Returns a sink object for the given component. * - * The sink returned by this function can be used to receive notifications - * whenever an instance of the given component is removed from an entity and - * thus destroyed.
+ * Use this function to receive notifications whenever an instance of the + * given component is removed from an entity and thus destroyed.
* The function type for a listener is equivalent to: * * @code{.cpp} * void(basic_registry &, Entity); * @endcode * - * Listeners are invoked **before** the component has been removed from the - * entity. + * Listeners are invoked **before** removing the component from the entity. * * @sa sink * - * @tparam Component Type of component of which to get the sink. + * @tparam Type Type of component of which to get the sink. * @return A temporary sink object. */ - template + template [[nodiscard]] auto on_destroy() { - return assure()->on_destroy(); + return assure().on_destroy(); } /** * @brief Returns a view for the given components. * - * This kind of objects are created on the fly and share with the registry - * its internal data structures.
- * Feel free to discard a view after the use. Creating and destroying a view - * is an incredibly cheap operation because they do not require any type of - * initialization.
- * As a rule of thumb, storing a view should never be an option. + * Views are created on the fly and share with the registry its internal + * data structures. Feel free to discard them after the use.
+ * Creating and destroying a view is an incredibly cheap operation. As a + * rule of thumb, storing a view should never be an option. * - * Views do their best to iterate the smallest set of candidate entities. - * In particular: - * - * * Single component views are incredibly fast and iterate a packed array - * of entities, all of which has the given component. - * * Multi component views look at the number of entities available for each - * component and pick up a reference to the smallest set of candidates to - * test for the given components. - * - * Views in no way affect the functionalities of the registry nor those of - * the underlying pools. - * - * @note - * Multi component views are pretty fast. However their performance tend to - * degenerate when the number of components to iterate grows up and the most - * of the entities have all the given components.
- * To get a performance boost, consider using a group instead. - * - * @tparam Component Type of components used to construct the view. + * @tparam Type Type of component used to construct the view. + * @tparam Other Other types of components used to construct the view. * @tparam Exclude Types of components used to filter the view. * @return A newly created view. */ - template - [[nodiscard]] basic_view, std::add_const_t...> view(exclude_t = {}) const { - static_assert(sizeof...(Component) > 0, "Exclusion-only views are not supported"); - return { *assure>()..., *assure()... }; + template + [[nodiscard]] basic_view, storage_for_type...>, exclude_t...>> + view(exclude_t = {}) const { + return {assure>(), assure>()..., assure>()...}; } /*! @copydoc view */ - template - [[nodiscard]] basic_view, Component...> view(exclude_t = {}) { - static_assert(sizeof...(Component) > 0, "Exclusion-only views are not supported"); - return { *assure>()..., *assure()... }; - } - - /** - * @brief Returns a runtime view for the given components. - * - * This kind of objects are created on the fly and share with the registry - * its internal data structures.
- * Users should throw away the view after use. Fortunately, creating and - * destroying a runtime view is an incredibly cheap operation because they - * do not require any type of initialization.
- * As a rule of thumb, storing a view should never be an option. - * - * Runtime views are to be used when users want to construct a view from - * some external inputs and don't know at compile-time what are the required - * components. - * - * @tparam ItComp Type of input iterator for the components to use to - * construct the view. - * @tparam ItExcl Type of input iterator for the components to use to filter - * the view. - * @param first An iterator to the first element of the range of components - * to use to construct the view. - * @param last An iterator past the last element of the range of components - * to use to construct the view. - * @param from An iterator to the first element of the range of components - * to use to filter the view. - * @param to An iterator past the last element of the range of components to - * use to filter the view. - * @return A newly created runtime view. - */ - template - [[nodiscard]] basic_runtime_view runtime_view(ItComp first, ItComp last, ItExcl from = {}, ItExcl to = {}) const { - std::vector component(std::distance(first, last)); - std::vector filter(std::distance(from, to)); - - std::transform(first, last, component.begin(), [this](const auto ctype) { - const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) { return pdata.poly && pdata.poly->value_type().hash() == ctype; }); - return it == pools.cend() ? nullptr : it->pool.get(); - }); - - std::transform(from, to, filter.begin(), [this](const auto ctype) { - const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) { return pdata.poly && pdata.poly->value_type().hash() == ctype; }); - return it == pools.cend() ? nullptr : it->pool.get(); - }); - - return { std::move(component), std::move(filter) }; + template + [[nodiscard]] basic_view, storage_for_type...>, exclude_t...>> + view(exclude_t = {}) { + return {assure>(), assure>()..., assure>()...}; } /** * @brief Returns a group for the given components. * - * This kind of objects are created on the fly and share with the registry - * its internal data structures.
- * Feel free to discard a group after the use. Creating and destroying a - * group is an incredibly cheap operation because they do not require any - * type of initialization, but for the first time they are requested.
- * As a rule of thumb, storing a group should never be an option. + * Groups are created on the fly and share with the registry its internal + * data structures. Feel free to discard them after the use.
+ * Creating and destroying a group is an incredibly cheap operation. As a + * rule of thumb, storing a group should never be an option. * * Groups support exclusion lists and can own types of components. The more * types are owned by a group, the faster it is to iterate entities and * components.
* However, groups also affect some features of the registry such as the - * creation and destruction of components, which will consequently be - * slightly slower (nothing that can be noticed in most cases). + * creation and destruction of components. * * @note * Pools of components that are owned by a group cannot be sorted anymore. * The group takes the ownership of the pools and arrange components so as * to iterate them as fast as possible. * - * @tparam Owned Types of components owned by the group. - * @tparam Get Types of components observed by the group. - * @tparam Exclude Types of components used to filter the group. + * @tparam Owned Type of storage _owned_ by the group. + * @tparam Get Type of storage _observed_ by the group. + * @tparam Exclude Type of storage used to filter the group. * @return A newly created group. */ template - [[nodiscard]] basic_group, get_t, Owned...> group(get_t, exclude_t = {}) { + [[nodiscard]] basic_group...>, get_t...>, exclude_t...>> + group(get_t = {}, exclude_t = {}) { static_assert(sizeof...(Owned) + sizeof...(Get) > 0, "Exclusion-only groups are not supported"); static_assert(sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude) > 1, "Single component groups are not allowed"); - using handler_type = group_handler, get_t...>, std::remove_const_t...>; + using handler_type = group_handler...>, get_t...>, std::remove_const_t...>; - const auto cpools = std::make_tuple(assure>()..., assure>()...); + const auto cpools = std::forward_as_tuple(assure>()..., assure>()...); constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude); handler_type *handler = nullptr; - if(auto it = std::find_if(groups.cbegin(), groups.cend(), [size](const auto &gdata) { + auto it = std::find_if(groups.cbegin(), groups.cend(), [size](const auto &gdata) { return gdata.size == size - && (gdata.owned(type_hash>::value()) && ...) - && (gdata.get(type_hash>::value()) && ...) - && (gdata.exclude(type_hash::value()) && ...); - }); it != groups.cend()) - { - handler = static_cast(it->group.get()); - } + && (gdata.owned(type_hash>::value()) && ...) + && (gdata.get(type_hash>::value()) && ...) + && (gdata.exclude(type_hash>::value()) && ...); + }); - if(!handler) { + if(it != groups.cend()) { + handler = static_cast(it->group.get()); + } else { group_data candidate = { size, - { new handler_type{}, [](void *instance) { delete static_cast(instance); } }, - []([[maybe_unused]] const id_type ctype) ENTT_NOEXCEPT { return ((ctype == type_hash>::value()) || ...); }, - []([[maybe_unused]] const id_type ctype) ENTT_NOEXCEPT { return ((ctype == type_hash>::value()) || ...); }, - []([[maybe_unused]] const id_type ctype) ENTT_NOEXCEPT { return ((ctype == type_hash::value()) || ...); }, + std::apply([this](auto &&...args) { return std::allocate_shared(get_allocator(), std::forward(args)...); }, entt::uses_allocator_construction_args(get_allocator())), + []([[maybe_unused]] const id_type ctype) noexcept { return ((ctype == type_hash>::value()) || ...); }, + []([[maybe_unused]] const id_type ctype) noexcept { return ((ctype == type_hash>::value()) || ...); }, + []([[maybe_unused]] const id_type ctype) noexcept { return ((ctype == type_hash>::value()) || ...); }, }; handler = static_cast(candidate.group.get()); @@ -1311,11 +1342,13 @@ public: if constexpr(sizeof...(Owned) == 0) { groups.push_back(std::move(candidate)); } else { - ENTT_ASSERT(std::all_of(groups.cbegin(), groups.cend(), [size](const auto &gdata) { + [[maybe_unused]] auto has_conflict = [size](const auto &gdata) { const auto overlapping = (0u + ... + gdata.owned(type_hash>::value())); - const auto sz = overlapping + (0u + ... + gdata.get(type_hash>::value())) + (0u + ... + gdata.exclude(type_hash::value())); + const auto sz = overlapping + (0u + ... + gdata.get(type_hash>::value())) + (0u + ... + gdata.exclude(type_hash>::value())); return !overlapping || ((sz == size) || (sz == gdata.size)); - }), "Conflicting groups"); + }; + + ENTT_ASSERT(std::all_of(groups.cbegin(), groups.cend(), std::move(has_conflict)), "Conflicting groups"); const auto next = std::find_if_not(groups.cbegin(), groups.cend(), [size](const auto &gdata) { return !(0u + ... + gdata.owned(type_hash>::value())) || (size > gdata.size); @@ -1332,11 +1365,11 @@ public: (on_construct>().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if>>(*handler), ...); (on_construct>().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if>>(*handler), ...); - (on_destroy().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if>(*handler), ...); + (on_destroy>().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if>>(*handler), ...); (on_destroy>().before(discard_if).template connect<&handler_type::discard_if>(*handler), ...); (on_destroy>().before(discard_if).template connect<&handler_type::discard_if>(*handler), ...); - (on_construct().before(discard_if).template connect<&handler_type::discard_if>(*handler), ...); + (on_construct>().before(discard_if).template connect<&handler_type::discard_if>(*handler), ...); if constexpr(sizeof...(Owned) == 0) { for(const auto entity: view(exclude)) { @@ -1344,133 +1377,87 @@ public: } } else { // we cannot iterate backwards because we want to leave behind valid entities in case of owned types - for(auto *first = std::get<0>(cpools)->data(), *last = first + std::get<0>(cpools)->size(); first != last; ++first) { + for(auto *first = std::get<0>(cpools).data(), *last = first + std::get<0>(cpools).size(); first != last; ++first) { handler->template maybe_valid_if...>>>(*this, *first); } } } - return { handler->current, *std::get> *>(cpools)..., *std::get> *>(cpools)... }; + return {handler->current, std::get> &>(cpools)..., std::get> &>(cpools)...}; } - /** - * @brief Returns a group for the given components. - * - * @sa group - * - * @tparam Owned Types of components owned by the group. - * @tparam Get Types of components observed by the group. - * @tparam Exclude Types of components used to filter the group. - * @return A newly created group. - */ + /*! @copydoc group */ template - [[nodiscard]] basic_group, get_t...>, std::add_const_t...> group_if_exists(get_t, exclude_t = {}) const { - if(auto it = std::find_if(groups.cbegin(), groups.cend(), [](const auto &gdata) { + [[nodiscard]] basic_group...>, get_t...>, exclude_t...>> + group_if_exists(get_t = {}, exclude_t = {}) const { + auto it = std::find_if(groups.cbegin(), groups.cend(), [](const auto &gdata) { return gdata.size == (sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude)) - && (gdata.owned(type_hash>::value()) && ...) - && (gdata.get(type_hash>::value()) && ...) - && (gdata.exclude(type_hash::value()) && ...); - }); it == groups.cend()) - { + && (gdata.owned(type_hash>::value()) && ...) + && (gdata.get(type_hash>::value()) && ...) + && (gdata.exclude(type_hash>::value()) && ...); + }); + + if(it == groups.cend()) { return {}; } else { - using handler_type = group_handler, get_t...>, std::remove_const_t...>; - return { static_cast(it->group.get())->current, *pool_if_exists>()... , *pool_if_exists>()... }; + using handler_type = group_handler...>, get_t...>, std::remove_const_t...>; + return {static_cast(it->group.get())->current, assure>()..., assure>()...}; } } - /** - * @brief Returns a group for the given components. - * - * @sa group - * - * @tparam Owned Types of components owned by the group. - * @tparam Exclude Types of components used to filter the group. - * @return A newly created group. - */ - template - [[nodiscard]] basic_group, get_t<>, Owned...> group(exclude_t = {}) { - return group(get_t<>{}, exclude); - } - - /** - * @brief Returns a group for the given components. - * - * @sa group_if_exists - * - * @tparam Owned Types of components owned by the group. - * @tparam Exclude Types of components used to filter the group. - * @return A newly created group. - */ - template - [[nodiscard]] basic_group, get_t<>, std::add_const_t...> group_if_exists(exclude_t = {}) const { - return group_if_exists...>(get_t<>{}, exclude); - } - /** * @brief Checks whether the given components belong to any group. * @tparam Component Types of components in which one is interested. - * @return True if the pools of the given components are sortable, false + * @return True if the pools of the given components are _free_, false * otherwise. */ - template - [[nodiscard]] bool sortable() const { - return std::none_of(groups.cbegin(), groups.cend(), [](auto &&gdata) { return (gdata.owned(type_hash>::value()) || ...); }); + template + [[nodiscard]] bool owned() const { + return std::any_of(groups.cbegin(), groups.cend(), [](auto &&gdata) { return (gdata.owned(type_hash>::value()) || ...); }); } /** * @brief Checks whether a group can be sorted. - * @tparam Owned Types of components owned by the group. - * @tparam Get Types of components observed by the group. - * @tparam Exclude Types of components used to filter the group. + * @tparam Owned Type of storage _owned_ by the group. + * @tparam Get Type of storage _observed_ by the group. + * @tparam Exclude Type of storage used to filter the group. * @return True if the group can be sorted, false otherwise. */ template - [[nodiscard]] bool sortable(const basic_group, get_t, Owned...> &) ENTT_NOEXCEPT { + [[nodiscard]] bool sortable(const basic_group, get_t, exclude_t> &) noexcept { constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude); - return std::find_if(groups.cbegin(), groups.cend(), [size](const auto &gdata) { - return (0u + ... + gdata.owned(type_hash>::value())) && (size < gdata.size); - }) == groups.cend(); + auto pred = [size](const auto &gdata) { return (0u + ... + gdata.owned(type_hash::value())) && (size < gdata.size); }; + return std::find_if(groups.cbegin(), groups.cend(), std::move(pred)) == groups.cend(); } /** - * @brief Sorts the pool of entities for the given component. + * @brief Sorts the elements of a given component. * - * The order of the elements in a pool is highly affected by assignments - * of components to entities and deletions. Components are arranged to - * maximize the performance during iterations and users should not make any - * assumption on the order.
- * This function can be used to impose an order to the elements in the pool - * of the given component. The order is kept valid until a component of the - * given type is assigned or removed from an entity. - * - * The comparison function object must return `true` if the first element - * is _less_ than the second one, `false` otherwise. The signature of the - * comparison function should be equivalent to one of the following: + * The order remains valid until a component of the given type is assigned + * to or removed from an entity.
+ * The comparison function object returns `true` if the first element is + * _less_ than the second one, `false` otherwise. Its signature is also + * equivalent to one of the following: * * @code{.cpp} * bool(const Entity, const Entity); - * bool(const Component &, const Component &); + * bool(const Type &, const Type &); * @endcode * - * Moreover, the comparison function object shall induce a - * _strict weak ordering_ on the values. - * - * The sort function oject must offer a member function template - * `operator()` that accepts three arguments: + * Moreover, it shall induce a _strict weak ordering_ on the values.
+ * The sort function object offers an `operator()` that accepts: * * * An iterator to the first element of the range to sort. * * An iterator past the last element of the range to sort. - * * A comparison function to use to compare the elements. + * * A comparison function object to use to compare the elements. * - * The comparison funtion object received by the sort function object hasn't - * necessarily the type of the one passed along with the other parameters to - * this member function. + * The comparison function object hasn't necessarily the type of the one + * passed along with the other parameters to this member function. * * @warning * Pools of components owned by a group cannot be sorted. * - * @tparam Component Type of components to sort. + * @tparam Type Type of components to sort. * @tparam Compare Type of comparison function object. * @tparam Sort Type of sort function object. * @tparam Args Types of arguments to forward to the sort function object. @@ -1478,38 +1465,31 @@ public: * @param algo A valid sort function object. * @param args Arguments to forward to the sort function object, if any. */ - template - void sort(Compare compare, Sort algo = Sort{}, Args &&... args) { - ENTT_ASSERT(sortable(), "Cannot sort owned storage"); - assure()->sort(std::move(compare), std::move(algo), std::forward(args)...); + template + void sort(Compare compare, Sort algo = Sort{}, Args &&...args) { + ENTT_ASSERT(!owned(), "Cannot sort owned storage"); + auto &cpool = assure(); + + if constexpr(std::is_invocable_v) { + auto comp = [&cpool, compare = std::move(compare)](const auto lhs, const auto rhs) { return compare(std::as_const(cpool.get(lhs)), std::as_const(cpool.get(rhs))); }; + cpool.sort(std::move(comp), std::move(algo), std::forward(args)...); + } else { + cpool.sort(std::move(compare), std::move(algo), std::forward(args)...); + } } /** * @brief Sorts two pools of components in the same way. * - * The order of the elements in a pool is highly affected by assignments - * of components to entities and deletions. Components are arranged to - * maximize the performance during iterations and users should not make any - * assumption on the order. + * Being `To` and `From` the two sets, after invoking this function an + * iterator for `To` returns elements according to the following rules: * - * It happens that different pools of components must be sorted the same way - * because of runtime and/or performance constraints. This function can be - * used to order a pool of components according to the order between the - * entities in another pool of components. - * - * @b How @b it @b works - * - * Being `A` and `B` the two sets where `B` is the master (the one the order - * of which rules) and `A` is the slave (the one to sort), after a call to - * this function an iterator for `A` will return the entities according to - * the following rules: - * - * * All the entities in `A` that are also in `B` are returned first - * according to the order they have in `B`. - * * All the entities in `A` that are not in `B` are returned in no + * * All entities in `To` that are also in `From` are returned first + * according to the order they have in `From`. + * * All entities in `To` that are not in `From` are returned in no * particular order after all the other entities. * - * Any subsequent change to `B` won't affect the order in `A`. + * Any subsequent change to `From` won't affect the order in `To`. * * @warning * Pools of components owned by a group cannot be sorted. @@ -1519,195 +1499,32 @@ public: */ template void sort() { - ENTT_ASSERT(sortable(), "Cannot sort owned storage"); - assure()->respect(*assure()); + ENTT_ASSERT(!owned(), "Cannot sort owned storage"); + assure().respect(assure()); } /** - * @brief Visits an entity and returns the type info for its components. - * - * The signature of the function should be equivalent to the following: - * - * @code{.cpp} - * void(const type_info); - * @endcode - * - * Returned identifiers are those of the components owned by the entity. - * - * @sa type_info - * - * @warning - * It's not specified whether a component attached to or removed from the - * given entity during the visit is returned or not to the caller. - * - * @tparam Func Type of the function object to invoke. - * @param entity A valid entity identifier. - * @param func A valid function object. + * @brief Returns the context object, that is, a general purpose container. + * @return The context object, that is, a general purpose container. */ - template - void visit(entity_type entity, Func func) const { - for(auto pos = pools.size(); pos; --pos) { - if(const auto &pdata = pools[pos-1]; pdata.pool && pdata.pool->contains(entity)) { - func(pdata.poly->value_type()); - } - } - } - - /** - * @brief Visits a registry and returns the type info for its components. - * - * The signature of the function should be equivalent to the following: - * - * @code{.cpp} - * void(const type_info); - * @endcode - * - * Returned identifiers are those of the components managed by the registry. - * - * @sa type_info - * - * @warning - * It's not specified whether a component for which a pool is created during - * the visit is returned or not to the caller. - * - * @tparam Func Type of the function object to invoke. - * @param func A valid function object. - */ - template - void visit(Func func) const { - for(auto pos = pools.size(); pos; --pos) { - if(const auto &pdata = pools[pos-1]; pdata.pool) { - func(pdata.poly->value_type()); - } - } - } - - /** - * @brief Binds an object to the context of the registry. - * - * If the value already exists it is overwritten, otherwise a new instance - * of the given type is created and initialized with the arguments provided. - * - * @tparam Type Type of object to set. - * @tparam Args Types of arguments to use to construct the object. - * @param args Parameters to use to initialize the value. - * @return A reference to the newly created object. - */ - template - Type & set(Args &&... args) { - unset(); - vars.emplace_back(std::in_place_type, std::forward(args)...); - return any_cast(vars.back()); - } - - /** - * @brief Unsets a context variable if it exists. - * @tparam Type Type of object to set. - */ - template - void unset() { - vars.erase(std::remove_if(vars.begin(), vars.end(), [type = type_id()](auto &&var) { return var.type() == type; }), vars.end()); - } - - /** - * @brief Binds an object to the context of the registry. - * - * In case the context doesn't contain the given object, the parameters - * provided are used to construct it. - * - * @tparam Type Type of object to set. - * @tparam Args Types of arguments to use to construct the object. - * @param args Parameters to use to initialize the object. - * @return A reference to the object in the context of the registry. - */ - template - [[nodiscard]] Type & ctx_or_set(Args &&... args) { - auto *value = try_ctx(); - return value ? *value : set(std::forward(args)...); - } - - /** - * @brief Returns a pointer to an object in the context of the registry. - * @tparam Type Type of object to get. - * @return A pointer to the object if it exists in the context of the - * registry, a null pointer otherwise. - */ - template - [[nodiscard]] std::add_const_t * try_ctx() const { - auto it = std::find_if(vars.cbegin(), vars.cend(), [type = type_id()](auto &&var) { return var.type() == type; }); - return it == vars.cend() ? nullptr : any_cast>(&*it); - } - - /*! @copydoc try_ctx */ - template - [[nodiscard]] Type * try_ctx() { - auto it = std::find_if(vars.begin(), vars.end(), [type = type_id()](auto &&var) { return var.type() == type; }); - return it == vars.end() ? nullptr : any_cast(&*it); - } - - /** - * @brief Returns a reference to an object in the context of the registry. - * - * @warning - * Attempting to get a context variable that doesn't exist results in - * undefined behavior. - * - * @tparam Type Type of object to get. - * @return A valid reference to the object in the context of the registry. - */ - template - [[nodiscard]] std::add_const_t & ctx() const { - auto it = std::find_if(vars.cbegin(), vars.cend(), [type = type_id()](auto &&var) { return var.type() == type; }); - ENTT_ASSERT(it != vars.cend(), "Invalid instance"); - return any_cast &>(*it); + context &ctx() noexcept { + return vars; } /*! @copydoc ctx */ - template - [[nodiscard]] Type & ctx() { - auto it = std::find_if(vars.begin(), vars.end(), [type = type_id()](auto &&var) { return var.type() == type; }); - ENTT_ASSERT(it != vars.end(), "Invalid instance"); - return any_cast(*it); - } - - /** - * @brief Visits a registry and returns the type info for its context - * variables. - * - * The signature of the function should be equivalent to the following: - * - * @code{.cpp} - * void(const type_info); - * @endcode - * - * Returned identifiers are those of the context variables currently set. - * - * @sa type_info - * - * @warning - * It's not specified whether a context variable created during the visit is - * returned or not to the caller. - * - * @tparam Func Type of the function object to invoke. - * @param func A valid function object. - */ - template - void ctx(Func func) const { - for(auto pos = vars.size(); pos; --pos) { - func(vars[pos-1].type()); - } + const context &ctx() const noexcept { + return vars; } private: - std::vector> vars{}; - mutable std::vector pools{}; - std::vector groups{}; - std::vector entities{}; - entity_type free_list{tombstone}; + context vars; + entity_type free_list; + std::vector epool; + // std::shared_ptr because of its type erased allocator which is useful here + dense_map, identity, std::equal_to, typename alloc_traits::template rebind_alloc>>> pools; + std::vector> groups; }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/entity/runtime_view.hpp b/LiteLoader/third-party/include/entt/entity/runtime_view.hpp index c00aa21..7ffad5c 100644 --- a/LiteLoader/third-party/include/entt/entity/runtime_view.hpp +++ b/LiteLoader/third-party/include/entt/entity/runtime_view.hpp @@ -1,23 +1,108 @@ #ifndef ENTT_ENTITY_RUNTIME_VIEW_HPP #define ENTT_ENTITY_RUNTIME_VIEW_HPP - -#include -#include -#include #include -#include -#include "third-party/include/entt/config/config.h" +#include +#include +#include +#include #include "entity.hpp" -#include "sparse_set.hpp" #include "fwd.hpp" - namespace entt { +/** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + +namespace internal { + +template +class runtime_view_iterator final { + using iterator_type = typename Set::iterator; + + [[nodiscard]] bool valid() const { + return (!tombstone_check || *it != tombstone) + && std::all_of(++pools->begin(), pools->end(), [entt = *it](const auto *curr) { return curr->contains(entt); }) + && std::none_of(filter->cbegin(), filter->cend(), [entt = *it](const auto *curr) { return curr && curr->contains(entt); }); + } + +public: + using difference_type = typename iterator_type::difference_type; + using value_type = typename iterator_type::value_type; + using pointer = typename iterator_type::pointer; + using reference = typename iterator_type::reference; + using iterator_category = std::bidirectional_iterator_tag; + + constexpr runtime_view_iterator() noexcept + : pools{}, + filter{}, + it{}, + tombstone_check{} {} + + runtime_view_iterator(const std::vector &cpools, const std::vector &ignore, iterator_type curr) noexcept + : pools{&cpools}, + filter{&ignore}, + it{curr}, + tombstone_check{pools->size() == 1u && (*pools)[0u]->policy() == deletion_policy::in_place} { + if(it != (*pools)[0]->end() && !valid()) { + ++(*this); + } + } + + runtime_view_iterator &operator++() { + while(++it != (*pools)[0]->end() && !valid()) {} + return *this; + } + + runtime_view_iterator operator++(int) { + runtime_view_iterator orig = *this; + return ++(*this), orig; + } + + runtime_view_iterator &operator--() { + while(--it != (*pools)[0]->begin() && !valid()) {} + return *this; + } + + runtime_view_iterator operator--(int) { + runtime_view_iterator orig = *this; + return operator--(), orig; + } + + [[nodiscard]] pointer operator->() const noexcept { + return it.operator->(); + } + + [[nodiscard]] reference operator*() const noexcept { + return *operator->(); + } + + [[nodiscard]] constexpr bool operator==(const runtime_view_iterator &other) const noexcept { + return it == other.it; + } + + [[nodiscard]] constexpr bool operator!=(const runtime_view_iterator &other) const noexcept { + return !(*this == other); + } + +private: + const std::vector *pools; + const std::vector *filter; + iterator_type it; + bool tombstone_check; +}; + +} // namespace internal /** - * @brief Runtime view. + * Internal details not to be documented. + * @endcond + */ + +/** + * @brief Generic runtime view. * * Runtime views iterate over those entities that have at least all the given * components in their bags. During initialization, a runtime view looks at the @@ -52,116 +137,122 @@ namespace entt { * Lifetime of a view must not overcome that of the registry that generated it. * In any other case, attempting to use a view results in undefined behavior. * - * @tparam Entity A valid entity type (see entt_traits for more details). + * @tparam Type Common base type. + * @tparam Allocator Type of allocator used to manage memory and elements. */ -template -class basic_runtime_view final { - using basic_common_type = basic_sparse_set; - using underlying_iterator = typename basic_common_type::iterator; - - class view_iterator final { - [[nodiscard]] bool valid() const { - const auto entt = *it; - - return (!stable_storage || (entt != tombstone)) - && std::all_of(pools->begin()++, pools->end(), [entt](const auto *curr) { return curr->contains(entt); }) - && std::none_of(filter->cbegin(), filter->cend(), [entt](const auto *curr) { return curr && curr->contains(entt); }); - } - - public: - using difference_type = typename underlying_iterator::difference_type; - using value_type = typename underlying_iterator::value_type; - using pointer = typename underlying_iterator::pointer; - using reference = typename underlying_iterator::reference; - using iterator_category = std::bidirectional_iterator_tag; - - view_iterator() ENTT_NOEXCEPT = default; - - view_iterator(const std::vector &cpools, const std::vector &ignore, underlying_iterator curr) ENTT_NOEXCEPT - : pools{&cpools}, - filter{&ignore}, - it{curr}, - stable_storage{std::any_of(pools->cbegin(), pools->cend(), [](const basic_common_type *cpool) { return (cpool->policy() == deletion_policy::in_place); })} - { - if(it != (*pools)[0]->end() && !valid()) { - ++(*this); - } - } - - view_iterator & operator++() { - while(++it != (*pools)[0]->end() && !valid()); - return *this; - } - - view_iterator operator++(int) { - view_iterator orig = *this; - return ++(*this), orig; - } - - view_iterator & operator--() ENTT_NOEXCEPT { - while(--it != (*pools)[0]->begin() && !valid()); - return *this; - } - - view_iterator operator--(int) ENTT_NOEXCEPT { - view_iterator orig = *this; - return operator--(), orig; - } - - [[nodiscard]] bool operator==(const view_iterator &other) const ENTT_NOEXCEPT { - return other.it == it; - } - - [[nodiscard]] bool operator!=(const view_iterator &other) const ENTT_NOEXCEPT { - return !(*this == other); - } - - [[nodiscard]] pointer operator->() const { - return it.operator->(); - } - - [[nodiscard]] reference operator*() const { - return *operator->(); - } - - private: - const std::vector *pools; - const std::vector *filter; - underlying_iterator it; - bool stable_storage; - }; - - [[nodiscard]] bool valid() const { - return !pools.empty() && pools.front(); - } +template +class basic_runtime_view { + using alloc_traits = std::allocator_traits; + static_assert(std::is_same_v, "Invalid value type"); + using container_type = std::vector; public: + /*! @brief Allocator type. */ + using allocator_type = Allocator; /*! @brief Underlying entity identifier. */ - using entity_type = Entity; + using entity_type = typename Type::entity_type; /*! @brief Unsigned integer type. */ using size_type = std::size_t; + /*! @brief Common type among all storage types. */ + using base_type = Type; /*! @brief Bidirectional iterator type. */ - using iterator = view_iterator; + using iterator = internal::runtime_view_iterator; /*! @brief Default constructor to use to create empty, invalid views. */ - basic_runtime_view() ENTT_NOEXCEPT - : pools{}, - filter{} - {} + basic_runtime_view() noexcept + : basic_runtime_view{allocator_type{}} {} /** - * @brief Constructs a runtime view from a set of storage classes. - * @param cpools The storage for the types to iterate. - * @param epools The storage for the types used to filter the view. + * @brief Constructs an empty, invalid view with a given allocator. + * @param allocator The allocator to use. */ - basic_runtime_view(std::vector cpools, std::vector epools) ENTT_NOEXCEPT - : pools{std::move(cpools)}, - filter{std::move(epools)} - { - // brings the best candidate (if any) on front of the vector - std::rotate(pools.begin(), std::min_element(pools.begin(), pools.end(), [](const auto *lhs, const auto *rhs) { - return (!lhs && rhs) || (lhs && rhs && lhs->size() < rhs->size()); - }), pools.end()); + explicit basic_runtime_view(const allocator_type &allocator) + : pools{allocator}, + filter{allocator} {} + + /*! @brief Default copy constructor. */ + basic_runtime_view(const basic_runtime_view &) = default; + + /** + * @brief Allocator-extended copy constructor. + * @param other The instance to copy from. + * @param allocator The allocator to use. + */ + basic_runtime_view(const basic_runtime_view &other, const allocator_type &allocator) + : pools{other.pools, allocator}, + filter{other.filter, allocator} {} + + /*! @brief Default move constructor. */ + basic_runtime_view(basic_runtime_view &&) noexcept(std::is_nothrow_move_constructible_v) = default; + + /** + * @brief Allocator-extended move constructor. + * @param other The instance to move from. + * @param allocator The allocator to use. + */ + basic_runtime_view(basic_runtime_view &&other, const allocator_type &allocator) + : pools{std::move(other.pools), allocator}, + filter{std::move(other.filter), allocator} {} + + /** + * @brief Default copy assignment operator. + * @return This container. + */ + basic_runtime_view &operator=(const basic_runtime_view &) = default; + + /** + * @brief Default move assignment operator. + * @return This container. + */ + basic_runtime_view &operator=(basic_runtime_view &&) noexcept(std::is_nothrow_move_assignable_v) = default; + + /** + * @brief Exchanges the contents with those of a given view. + * @param other View to exchange the content with. + */ + void swap(basic_runtime_view &other) { + using std::swap; + swap(pools, other.pools); + swap(filter, other.filter); + } + + /** + * @brief Returns the associated allocator. + * @return The associated allocator. + */ + [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { + return pools.get_allocator(); + } + + /*! @brief Clears the view. */ + void clear() { + pools.clear(); + filter.clear(); + } + + /** + * @brief Appends an opaque storage object to a runtime view. + * @param base An opaque reference to a storage object. + * @return This runtime view. + */ + basic_runtime_view &iterate(base_type &base) { + if(pools.empty() || !(base.size() < pools[0u]->size())) { + pools.push_back(&base); + } else { + pools.push_back(std::exchange(pools[0u], &base)); + } + + return *this; + } + + /** + * @brief Adds an opaque storage object as a filter of a runtime view. + * @param base An opaque reference to a storage object. + * @return This runtime view. + */ + basic_runtime_view &exclude(base_type &base) { + filter.push_back(&base); + return *this; } /** @@ -169,7 +260,7 @@ public: * @return Estimated number of entities iterated by the view. */ [[nodiscard]] size_type size_hint() const { - return valid() ? pools.front()->size() : size_type{}; + return pools.empty() ? size_type{} : pools.front()->size(); } /** @@ -183,7 +274,7 @@ public: * @return An iterator to the first entity that has the given components. */ [[nodiscard]] iterator begin() const { - return valid() ? iterator{pools, filter, pools[0]->begin()} : iterator{}; + return pools.empty() ? iterator{} : iterator{pools, filter, pools[0]->begin()}; } /** @@ -198,17 +289,18 @@ public: * given components. */ [[nodiscard]] iterator end() const { - return valid() ? iterator{pools, filter, pools[0]->end()} : iterator{}; + return pools.empty() ? iterator{} : iterator{pools, filter, pools[0]->end()}; } /** * @brief Checks if a view contains an entity. - * @param entt A valid entity identifier. + * @param entt A valid identifier. * @return True if the view contains the given entity, false otherwise. */ [[nodiscard]] bool contains(const entity_type entt) const { - return valid() && std::all_of(pools.cbegin(), pools.cend(), [entt](const auto *curr) { return curr->contains(entt); }) - && std::none_of(filter.cbegin(), filter.cend(), [entt](const auto *curr) { return curr && curr->contains(entt); }); + return !pools.empty() + && std::all_of(pools.cbegin(), pools.cend(), [entt](const auto *curr) { return curr->contains(entt); }) + && std::none_of(filter.cbegin(), filter.cend(), [entt](const auto *curr) { return curr && curr->contains(entt); }); } /** @@ -234,12 +326,10 @@ public: } private: - std::vector pools; - std::vector filter; + container_type pools; + container_type filter; }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/entity/snapshot.hpp b/LiteLoader/third-party/include/entt/entity/snapshot.hpp index 153a574..d60befc 100644 --- a/LiteLoader/third-party/include/entt/entity/snapshot.hpp +++ b/LiteLoader/third-party/include/entt/entity/snapshot.hpp @@ -1,25 +1,23 @@ #ifndef ENTT_ENTITY_SNAPSHOT_HPP #define ENTT_ENTITY_SNAPSHOT_HPP - #include #include #include #include #include -#include #include #include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/type_traits.hpp" +#include "../config/config.h" +#include "../container/dense_map.hpp" +#include "../core/type_traits.hpp" +#include "component.hpp" #include "entity.hpp" #include "fwd.hpp" -#include "registry.hpp" - +#include "view.hpp" namespace entt { - /** * @brief Utility class to create snapshots from a registry. * @@ -28,16 +26,16 @@ namespace entt { * This type can be used in both cases if provided with a correctly configured * output archive. * - * @tparam Entity A valid entity type (see entt_traits for more details). + * @tparam Registry Basic registry type. */ -template +template class basic_snapshot { - using traits_type = entt_traits; + using entity_traits = entt_traits; template void get(Archive &archive, std::size_t sz, It first, It last) const { - const auto view = reg->template view>(); - archive(typename traits_type::entity_type(sz)); + const auto view = reg->template view(); + archive(typename entity_traits::entity_type(sz)); while(first != last) { const auto entt = *(first++); @@ -62,22 +60,23 @@ class basic_snapshot { } public: + /*! Basic registry type. */ + using registry_type = Registry; /*! @brief Underlying entity identifier. */ - using entity_type = Entity; + using entity_type = typename registry_type::entity_type; /** * @brief Constructs an instance that is bound to a given registry. * @param source A valid reference to a registry. */ - basic_snapshot(const basic_registry &source) ENTT_NOEXCEPT - : reg{&source} - {} + basic_snapshot(const registry_type &source) noexcept + : reg{&source} {} /*! @brief Default move constructor. */ - basic_snapshot(basic_snapshot &&) = default; + basic_snapshot(basic_snapshot &&) noexcept = default; /*! @brief Default move assignment operator. @return This snapshot. */ - basic_snapshot & operator=(basic_snapshot &&) = default; + basic_snapshot &operator=(basic_snapshot &&) noexcept = default; /** * @brief Puts aside all the entities from the underlying registry. @@ -90,17 +89,16 @@ public: * @return An object of this type to continue creating the snapshot. */ template - const basic_snapshot & entities(Archive &archive) const { + const basic_snapshot &entities(Archive &archive) const { const auto sz = reg->size(); - archive(typename traits_type::entity_type(sz)); + archive(typename entity_traits::entity_type(sz + 1u)); + archive(reg->released()); for(auto first = reg->data(), last = first + sz; first != last; ++first) { archive(*first); } - archive(reg->released()); - return *this; } @@ -116,10 +114,10 @@ public: * @return An object of this type to continue creating the snapshot. */ template - const basic_snapshot & component(Archive &archive) const { + const basic_snapshot &component(Archive &archive) const { if constexpr(sizeof...(Component) == 1u) { const auto view = reg->template view(); - (component(archive, view.data(), view.data() + view.size()), ...); + (component(archive, view.rbegin(), view.rend()), ...); return *this; } else { (component(archive), ...); @@ -142,16 +140,15 @@ public: * @return An object of this type to continue creating the snapshot. */ template - const basic_snapshot & component(Archive &archive, It first, It last) const { + const basic_snapshot &component(Archive &archive, It first, It last) const { component(archive, first, last, std::index_sequence_for{}); return *this; } private: - const basic_registry *reg; + const registry_type *reg; }; - /** * @brief Utility class to restore a snapshot as a whole. * @@ -160,58 +157,59 @@ private: * originally had.
* An example of use is the implementation of a save/restore utility. * - * @tparam Entity A valid entity type (see entt_traits for more details). + * @tparam Registry Basic registry type. */ -template +template class basic_snapshot_loader { - using traits_type = entt_traits; + using entity_traits = entt_traits; - template + template void assign(Archive &archive) const { - typename traits_type::entity_type length{}; + typename entity_traits::entity_type length{}; + entity_type entt; + archive(length); - entity_type entt{}; - - if constexpr(std::tuple_size_vtemplate view().get({}))> == 0) { + if constexpr(ignore_as_empty_v) { while(length--) { archive(entt); const auto entity = reg->valid(entt) ? entt : reg->create(entt); ENTT_ASSERT(entity == entt, "Entity not available for use"); - reg->template emplace(entity); + reg->template emplace(entt); } } else { - Type instance{}; + Component instance; while(length--) { archive(entt, instance); const auto entity = reg->valid(entt) ? entt : reg->create(entt); ENTT_ASSERT(entity == entt, "Entity not available for use"); - reg->template emplace(entity, std::move(instance)); + reg->template emplace(entt, std::move(instance)); } } } public: + /*! Basic registry type. */ + using registry_type = Registry; /*! @brief Underlying entity identifier. */ - using entity_type = Entity; + using entity_type = typename registry_type::entity_type; /** * @brief Constructs an instance that is bound to a given registry. * @param source A valid reference to a registry. */ - basic_snapshot_loader(basic_registry &source) ENTT_NOEXCEPT - : reg{&source} - { + basic_snapshot_loader(registry_type &source) noexcept + : reg{&source} { // restoring a snapshot as a whole requires a clean registry ENTT_ASSERT(reg->empty(), "Registry must be empty"); } /*! @brief Default move constructor. */ - basic_snapshot_loader(basic_snapshot_loader &&) = default; + basic_snapshot_loader(basic_snapshot_loader &&) noexcept = default; /*! @brief Default move assignment operator. @return This loader. */ - basic_snapshot_loader & operator=(basic_snapshot_loader &&) = default; + basic_snapshot_loader &operator=(basic_snapshot_loader &&) noexcept = default; /** * @brief Restores entities that were in use during serialization. @@ -224,20 +222,17 @@ public: * @return A valid loader to continue restoring data. */ template - const basic_snapshot_loader & entities(Archive &archive) const { - typename traits_type::entity_type length{}; + const basic_snapshot_loader &entities(Archive &archive) const { + typename entity_traits::entity_type length{}; archive(length); std::vector all(length); - for(decltype(length) pos{}; pos < length; ++pos) { + for(std::size_t pos{}; pos < length; ++pos) { archive(all[pos]); } - entity_type destroyed; - archive(destroyed); - - reg->assign(all.cbegin(), all.cend(), destroyed); + reg->assign(++all.cbegin(), all.cend(), all[0u]); return *this; } @@ -256,7 +251,7 @@ public: * @return A valid loader to continue restoring data. */ template - const basic_snapshot_loader & component(Archive &archive) const { + const basic_snapshot_loader &component(Archive &archive) const { (assign(archive), ...); return *this; } @@ -271,19 +266,20 @@ public: * * @return A valid loader to continue restoring data. */ - const basic_snapshot_loader & orphans() const { - reg->orphans([this](const auto entt) { - reg->release(entt); + const basic_snapshot_loader &orphans() const { + reg->each([this](const auto entt) { + if(reg->orphan(entt)) { + reg->release(entt); + } }); return *this; } private: - basic_registry *reg; + registry_type *reg; }; - /** * @brief Utility class for _continuous loading_. * @@ -298,13 +294,13 @@ private: * the requirement of transferring somehow parts of the representation side to * side. * - * @tparam Entity A valid entity type (see entt_traits for more details). + * @tparam Registry Basic registry type. */ -template +template class basic_continuous_loader { - using traits_type = entt_traits; + using entity_traits = entt_traits; - void destroy(Entity entt) { + void destroy(typename Registry::entity_type entt) { if(const auto it = remloc.find(entt); it == remloc.cend()) { const auto local = reg->create(); remloc.emplace(entt, std::make_pair(local, true)); @@ -312,7 +308,7 @@ class basic_continuous_loader { } } - void restore(Entity entt) { + void restore(typename Registry::entity_type entt) { const auto it = remloc.find(entt); if(it == remloc.cend()) { @@ -329,8 +325,7 @@ class basic_continuous_loader { } template - auto update(int, Container &container) - -> decltype(typename Container::mapped_type{}, void()) { + auto update(int, Container &container) -> decltype(typename Container::mapped_type{}, void()) { // map like container Container other; @@ -348,12 +343,12 @@ class basic_continuous_loader { } } - std::swap(container, other); + using std::swap; + swap(container, other); } template - auto update(char, Container &container) - -> decltype(typename Container::value_type{}, void()) { + auto update(char, Container &container) -> decltype(typename Container::value_type{}, void()) { // vector like container static_assert(std::is_same_v, "Invalid value type"); @@ -362,9 +357,9 @@ class basic_continuous_loader { } } - template - void update([[maybe_unused]] Other &instance, [[maybe_unused]] Member Type:: *member) { - if constexpr(!std::is_same_v) { + template + void update([[maybe_unused]] Component &instance, [[maybe_unused]] Member Other::*member) { + if constexpr(!std::is_same_v) { return; } else if constexpr(std::is_same_v) { instance.*member = map(instance.*member); @@ -385,48 +380,49 @@ class basic_continuous_loader { } } - template - void assign(Archive &archive, [[maybe_unused]] Member Type:: *... member) { - typename traits_type::entity_type length{}; + template + void assign(Archive &archive, [[maybe_unused]] Member Other::*...member) { + typename entity_traits::entity_type length{}; + entity_type entt; + archive(length); - entity_type entt{}; - - if constexpr(std::tuple_size_vtemplate view().get({}))> == 0) { + if constexpr(ignore_as_empty_v) { while(length--) { archive(entt); restore(entt); - reg->template emplace_or_replace(map(entt)); + reg->template emplace_or_replace(map(entt)); } } else { - Other instance{}; + Component instance; while(length--) { archive(entt, instance); (update(instance, member), ...); restore(entt); - reg->template emplace_or_replace(map(entt), std::move(instance)); + reg->template emplace_or_replace(map(entt), std::move(instance)); } } } public: + /*! Basic registry type. */ + using registry_type = Registry; /*! @brief Underlying entity identifier. */ - using entity_type = Entity; + using entity_type = typename registry_type::entity_type; /** * @brief Constructs an instance that is bound to a given registry. * @param source A valid reference to a registry. */ - basic_continuous_loader(basic_registry &source) ENTT_NOEXCEPT - : reg{&source} - {} + basic_continuous_loader(registry_type &source) noexcept + : reg{&source} {} /*! @brief Default move constructor. */ basic_continuous_loader(basic_continuous_loader &&) = default; /*! @brief Default move assignment operator. @return This loader. */ - basic_continuous_loader & operator=(basic_continuous_loader &&) = default; + basic_continuous_loader &operator=(basic_continuous_loader &&) = default; /** * @brief Restores entities that were in use during serialization. @@ -439,25 +435,24 @@ public: * @return A non-const reference to this loader. */ template - basic_continuous_loader & entities(Archive &archive) { - typename traits_type::entity_type length{}; + basic_continuous_loader &entities(Archive &archive) { + typename entity_traits::entity_type length{}; entity_type entt{}; archive(length); + // discards the head of the list of destroyed entities + archive(entt); - for(decltype(length) pos{}; pos < length; ++pos) { + for(std::size_t pos{}, last = length - 1u; pos < last; ++pos) { archive(entt); - if(const auto entity = traits_type::to_entity(entt); entity == pos) { + if(const auto entity = entity_traits::to_entity(entt); entity == pos) { restore(entt); } else { destroy(entt); } } - // discards the head of the list of destroyed entities - archive(entt); - return *this; } @@ -474,14 +469,14 @@ public: * * @tparam Component Type of component to restore. * @tparam Archive Type of input archive. - * @tparam Type Types of components to update with local counterparts. + * @tparam Other Types of components to update with local counterparts. * @tparam Member Types of members to update with their local counterparts. * @param archive A valid reference to an input archive. * @param member Members to update with their local counterparts. * @return A non-const reference to this loader. */ - template - basic_continuous_loader & component(Archive &archive, Member Type:: *... member) { + template + basic_continuous_loader &component(Archive &archive, Member Other::*...member) { (remove_if_exists(), ...); (assign(archive, member...), ...); return *this; @@ -495,7 +490,7 @@ public: * * @return A non-const reference to this loader. */ - basic_continuous_loader & shrink() { + basic_continuous_loader &shrink() { auto it = remloc.begin(); while(it != remloc.cend()) { @@ -527,9 +522,11 @@ public: * * @return A non-const reference to this loader. */ - basic_continuous_loader & orphans() { - reg->orphans([this](const auto entt) { - reg->release(entt); + basic_continuous_loader &orphans() { + reg->each([this](const auto entt) { + if(reg->orphan(entt)) { + reg->release(entt); + } }); return *this; @@ -537,19 +534,19 @@ public: /** * @brief Tests if a loader knows about a given entity. - * @param entt An entity identifier. + * @param entt A valid identifier. * @return True if `entity` is managed by the loader, false otherwise. */ - [[nodiscard]] bool contains(entity_type entt) const ENTT_NOEXCEPT { + [[nodiscard]] bool contains(entity_type entt) const noexcept { return (remloc.find(entt) != remloc.cend()); } /** * @brief Returns the identifier to which an entity refers. - * @param entt An entity identifier. + * @param entt A valid identifier. * @return The local identifier if any, the null entity otherwise. */ - [[nodiscard]] entity_type map(entity_type entt) const ENTT_NOEXCEPT { + [[nodiscard]] entity_type map(entity_type entt) const noexcept { const auto it = remloc.find(entt); entity_type other = null; @@ -561,12 +558,10 @@ public: } private: - std::unordered_map> remloc; - basic_registry *reg; + dense_map> remloc; + registry_type *reg; }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/entity/sparse_set.hpp b/LiteLoader/third-party/include/entt/entity/sparse_set.hpp index 4c57dbf..96aa172 100644 --- a/LiteLoader/third-party/include/entt/entity/sparse_set.hpp +++ b/LiteLoader/third-party/include/entt/entity/sparse_set.hpp @@ -1,31 +1,152 @@ #ifndef ENTT_ENTITY_SPARSE_SET_HPP #define ENTT_ENTITY_SPARSE_SET_HPP - #include #include #include #include #include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/algorithm.hpp" -#include "third-party/include/entt/core/fwd.hpp" +#include +#include "../config/config.h" +#include "../core/algorithm.hpp" +#include "../core/any.hpp" +#include "../core/memory.hpp" +#include "../core/type_info.hpp" #include "entity.hpp" #include "fwd.hpp" - namespace entt { +/** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + +namespace internal { + +template +struct sparse_set_iterator final { + using value_type = typename Container::value_type; + using pointer = typename Container::const_pointer; + using reference = typename Container::const_reference; + using difference_type = typename Container::difference_type; + using iterator_category = std::random_access_iterator_tag; + + constexpr sparse_set_iterator() noexcept + : packed{}, + offset{} {} + + constexpr sparse_set_iterator(const Container &ref, const difference_type idx) noexcept + : packed{std::addressof(ref)}, + offset{idx} {} + + constexpr sparse_set_iterator &operator++() noexcept { + return --offset, *this; + } + + constexpr sparse_set_iterator operator++(int) noexcept { + sparse_set_iterator orig = *this; + return ++(*this), orig; + } + + constexpr sparse_set_iterator &operator--() noexcept { + return ++offset, *this; + } + + constexpr sparse_set_iterator operator--(int) noexcept { + sparse_set_iterator orig = *this; + return operator--(), orig; + } + + constexpr sparse_set_iterator &operator+=(const difference_type value) noexcept { + offset -= value; + return *this; + } + + constexpr sparse_set_iterator operator+(const difference_type value) const noexcept { + sparse_set_iterator copy = *this; + return (copy += value); + } + + constexpr sparse_set_iterator &operator-=(const difference_type value) noexcept { + return (*this += -value); + } + + constexpr sparse_set_iterator operator-(const difference_type value) const noexcept { + return (*this + -value); + } + + [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept { + return packed->data()[index() - value]; + } + + [[nodiscard]] constexpr pointer operator->() const noexcept { + return packed->data() + index(); + } + + [[nodiscard]] constexpr reference operator*() const noexcept { + return *operator->(); + } + + [[nodiscard]] constexpr difference_type index() const noexcept { + return offset - 1; + } + +private: + const Container *packed; + difference_type offset; +}; + +template +[[nodiscard]] constexpr std::ptrdiff_t operator-(const sparse_set_iterator &lhs, const sparse_set_iterator &rhs) noexcept { + return rhs.index() - lhs.index(); +} + +template +[[nodiscard]] constexpr bool operator==(const sparse_set_iterator &lhs, const sparse_set_iterator &rhs) noexcept { + return lhs.index() == rhs.index(); +} + +template +[[nodiscard]] constexpr bool operator!=(const sparse_set_iterator &lhs, const sparse_set_iterator &rhs) noexcept { + return !(lhs == rhs); +} + +template +[[nodiscard]] constexpr bool operator<(const sparse_set_iterator &lhs, const sparse_set_iterator &rhs) noexcept { + return lhs.index() > rhs.index(); +} + +template +[[nodiscard]] constexpr bool operator>(const sparse_set_iterator &lhs, const sparse_set_iterator &rhs) noexcept { + return lhs.index() < rhs.index(); +} + +template +[[nodiscard]] constexpr bool operator<=(const sparse_set_iterator &lhs, const sparse_set_iterator &rhs) noexcept { + return !(lhs > rhs); +} + +template +[[nodiscard]] constexpr bool operator>=(const sparse_set_iterator &lhs, const sparse_set_iterator &rhs) noexcept { + return !(lhs < rhs); +} + +} // namespace internal + +/** + * Internal details not to be documented. + * @endcond + */ /*! @brief Sparse set deletion policy. */ -enum class deletion_policy: std::uint8_t { +enum class deletion_policy : std::uint8_t { /*! @brief Swap-and-pop deletion policy. */ swap_and_pop = 0u, /*! @brief In-place deletion policy. */ in_place = 1u }; - /** * @brief Basic sparse set implementation. * @@ -51,286 +172,214 @@ enum class deletion_policy: std::uint8_t { */ template class basic_sparse_set { - static constexpr auto growth_factor = 1.5; - static constexpr auto sparse_page = ENTT_SPARSE_PAGE; + using alloc_traits = std::allocator_traits; + static_assert(std::is_same_v, "Invalid value type"); + using sparse_container_type = std::vector>; + using packed_container_type = std::vector; + using entity_traits = entt_traits; - using traits_type = entt_traits; - - using alloc_traits = typename std::allocator_traits::template rebind_traits; - using alloc_pointer = typename alloc_traits::pointer; - using alloc_const_pointer = typename alloc_traits::const_pointer; - - using bucket_alloc_traits = typename std::allocator_traits::template rebind_traits; - using bucket_alloc_pointer = typename bucket_alloc_traits::pointer; - - static_assert(alloc_traits::propagate_on_container_move_assignment::value); - static_assert(bucket_alloc_traits::propagate_on_container_move_assignment::value); - - struct sparse_set_iterator final { - using difference_type = typename traits_type::difference_type; - using value_type = Entity; - using pointer = const value_type *; - using reference = const value_type &; - using iterator_category = std::random_access_iterator_tag; - - sparse_set_iterator() ENTT_NOEXCEPT = default; - - sparse_set_iterator(const alloc_const_pointer *ref, const difference_type idx) ENTT_NOEXCEPT - : packed{ref}, - index{idx} - {} - - sparse_set_iterator & operator++() ENTT_NOEXCEPT { - return --index, *this; - } - - sparse_set_iterator operator++(int) ENTT_NOEXCEPT { - iterator orig = *this; - return ++(*this), orig; - } - - sparse_set_iterator & operator--() ENTT_NOEXCEPT { - return ++index, *this; - } - - sparse_set_iterator operator--(int) ENTT_NOEXCEPT { - sparse_set_iterator orig = *this; - return operator--(), orig; - } - - sparse_set_iterator & operator+=(const difference_type value) ENTT_NOEXCEPT { - index -= value; - return *this; - } - - sparse_set_iterator operator+(const difference_type value) const ENTT_NOEXCEPT { - sparse_set_iterator copy = *this; - return (copy += value); - } - - sparse_set_iterator & operator-=(const difference_type value) ENTT_NOEXCEPT { - return (*this += -value); - } - - sparse_set_iterator operator-(const difference_type value) const ENTT_NOEXCEPT { - return (*this + -value); - } - - difference_type operator-(const sparse_set_iterator &other) const ENTT_NOEXCEPT { - return other.index - index; - } - - [[nodiscard]] reference operator[](const difference_type value) const { - const auto pos = size_type(index-value-1u); - return (*packed)[pos]; - } - - [[nodiscard]] bool operator==(const sparse_set_iterator &other) const ENTT_NOEXCEPT { - return other.index == index; - } - - [[nodiscard]] bool operator!=(const sparse_set_iterator &other) const ENTT_NOEXCEPT { - return !(*this == other); - } - - [[nodiscard]] bool operator<(const sparse_set_iterator &other) const ENTT_NOEXCEPT { - return index > other.index; - } - - [[nodiscard]] bool operator>(const sparse_set_iterator &other) const ENTT_NOEXCEPT { - return index < other.index; - } - - [[nodiscard]] bool operator<=(const sparse_set_iterator &other) const ENTT_NOEXCEPT { - return !(*this > other); - } - - [[nodiscard]] bool operator>=(const sparse_set_iterator &other) const ENTT_NOEXCEPT { - return !(*this < other); - } - - [[nodiscard]] pointer operator->() const { - const auto pos = size_type(index-1u); - return std::addressof((*packed)[pos]); - } - - [[nodiscard]] reference operator*() const { - return *operator->(); - } - - private: - const alloc_const_pointer *packed; - difference_type index; - }; - - [[nodiscard]] static auto page(const Entity entt) ENTT_NOEXCEPT { - return static_cast(traits_type::to_entity(entt) / sparse_page); + [[nodiscard]] auto sparse_ptr(const Entity entt) const { + const auto pos = static_cast(entity_traits::to_entity(entt)); + const auto page = pos / entity_traits::page_size; + return (page < sparse.size() && sparse[page]) ? (sparse[page] + fast_mod(pos, entity_traits::page_size)) : nullptr; } - [[nodiscard]] static auto offset(const Entity entt) ENTT_NOEXCEPT { - return static_cast(traits_type::to_entity(entt) & (sparse_page - 1)); + [[nodiscard]] auto &sparse_ref(const Entity entt) const { + ENTT_ASSERT(sparse_ptr(entt), "Invalid element"); + const auto pos = static_cast(entity_traits::to_entity(entt)); + return sparse[pos / entity_traits::page_size][fast_mod(pos, entity_traits::page_size)]; } - [[nodiscard]] auto assure_page(const std::size_t idx) { - if(!(idx < bucket)) { - const size_type sz = idx + 1u; - const auto mem = bucket_alloc_traits::allocate(bucket_allocator, sz); + [[nodiscard]] auto &assure_at_least(const Entity entt) { + const auto pos = static_cast(entity_traits::to_entity(entt)); + const auto page = pos / entity_traits::page_size; - std::uninitialized_value_construct(mem + bucket, mem + sz); - std::uninitialized_copy(sparse, sparse + bucket, mem); - - std::destroy(sparse, sparse + bucket); - bucket_alloc_traits::deallocate(bucket_allocator, sparse, bucket); - - sparse = mem; - bucket = sz; + if(!(page < sparse.size())) { + sparse.resize(page + 1u, nullptr); } - if(!sparse[idx]) { - sparse[idx] = alloc_traits::allocate(allocator, sparse_page); - std::uninitialized_fill(sparse[idx], sparse[idx] + sparse_page, null); + if(!sparse[page]) { + auto page_allocator{packed.get_allocator()}; + sparse[page] = alloc_traits::allocate(page_allocator, entity_traits::page_size); + std::uninitialized_fill(sparse[page], sparse[page] + entity_traits::page_size, null); } - return sparse[idx]; + auto &elem = sparse[page][fast_mod(pos, entity_traits::page_size)]; + ENTT_ASSERT(elem == null, "Slot not available"); + return elem; } - void resize_packed(const std::size_t req) { - ENTT_ASSERT((req != reserved) && !(req < count), "Invalid request"); - const auto mem = alloc_traits::allocate(allocator, req); + void release_sparse_pages() { + auto page_allocator{packed.get_allocator()}; - std::uninitialized_copy(packed, packed + count, mem); - std::uninitialized_fill(mem + count, mem + req, tombstone); - - std::destroy(packed, packed + reserved); - alloc_traits::deallocate(allocator, packed, reserved); - - packed = mem; - reserved = req; - } - - void release_memory() { - if(packed) { - for(size_type pos{}; pos < bucket; ++pos) { - if(sparse[pos]) { - std::destroy(sparse[pos], sparse[pos] + sparse_page); - alloc_traits::deallocate(allocator, sparse[pos], sparse_page); - } + for(auto &&page: sparse) { + if(page != nullptr) { + std::destroy(page, page + entity_traits::page_size); + alloc_traits::deallocate(page_allocator, page, entity_traits::page_size); + page = nullptr; } - - std::destroy(packed, packed + reserved); - std::destroy(sparse, sparse + bucket); - alloc_traits::deallocate(allocator, packed, reserved); - bucket_alloc_traits::deallocate(bucket_allocator, sparse, bucket); } } +private: + virtual const void *get_at(const std::size_t) const { + return nullptr; + } + + virtual void swap_at(const std::size_t, const std::size_t) {} + virtual void move_element(const std::size_t, const std::size_t) {} + +protected: + /*! @brief Random access iterator type. */ + using basic_iterator = internal::sparse_set_iterator; + + /** + * @brief Erases an entity from a sparse set. + * @param it An iterator to the element to pop. + */ + void swap_and_pop(const basic_iterator it) { + ENTT_ASSERT(mode == deletion_policy::swap_and_pop, "Deletion policy mismatched"); + auto &self = sparse_ref(*it); + const auto entt = entity_traits::to_entity(self); + sparse_ref(packed.back()) = entity_traits::combine(entt, entity_traits::to_integral(packed.back())); + packed[static_cast(entt)] = packed.back(); + // unnecessary but it helps to detect nasty bugs + ENTT_ASSERT((packed.back() = null, true), ""); + // lazy self-assignment guard + self = null; + packed.pop_back(); + } + + /** + * @brief Erases an entity from a sparse set. + * @param it An iterator to the element to pop. + */ + void in_place_pop(const basic_iterator it) { + ENTT_ASSERT(mode == deletion_policy::in_place, "Deletion policy mismatched"); + const auto entt = entity_traits::to_entity(std::exchange(sparse_ref(*it), null)); + packed[static_cast(entt)] = std::exchange(free_list, entity_traits::combine(entt, entity_traits::reserved)); + } + protected: /** - * @brief Swaps two entities in the internal packed array. - * @param lhs A valid position of an entity within storage. - * @param rhs A valid position of an entity within storage. + * @brief Erases entities from a sparse set. + * @param first An iterator to the first element of the range of entities. + * @param last An iterator past the last element of the range of entities. */ - virtual void swap_at([[maybe_unused]] const std::size_t lhs, [[maybe_unused]] const std::size_t rhs) {} - - /** - * @brief Moves an entity in the internal packed array. - * @param from A valid position of an entity within storage. - * @param to A valid position of an entity within storage. - */ - virtual void move_and_pop([[maybe_unused]] const std::size_t from, [[maybe_unused]] const std::size_t to) {} - - /** - * @brief Attempts to erase an entity from the internal packed array. - * @param entt A valid entity identifier. - * @param ud Optional user data that are forwarded as-is to derived classes. - */ - virtual void swap_and_pop(const Entity entt, [[maybe_unused]] void *ud) { - auto &ref = sparse[page(entt)][offset(entt)]; - const auto pos = static_cast(traits_type::to_entity(ref)); - ENTT_ASSERT(packed[pos] == entt, "Invalid entity identifier"); - auto &last = packed[--count]; - - packed[pos] = last; - sparse[page(last)][offset(last)] = ref; - // lazy self-assignment guard - ref = null; - // unnecessary but it helps to detect nasty bugs - ENTT_ASSERT((last = tombstone, true), ""); + virtual void pop(basic_iterator first, basic_iterator last) { + if(mode == deletion_policy::swap_and_pop) { + for(; first != last; ++first) { + swap_and_pop(first); + } + } else { + for(; first != last; ++first) { + in_place_pop(first); + } + } } /** - * @brief Attempts to erase an entity from the internal packed array. - * @param entt A valid entity identifier. - * @param ud Optional user data that are forwarded as-is to derived classes. + * @brief Assigns an entity to a sparse set. + * @param entt A valid identifier. + * @param force_back Force back insertion. + * @return Iterator pointing to the emplaced element. */ - virtual void in_place_pop(const Entity entt, [[maybe_unused]] void *ud) { - auto &ref = sparse[page(entt)][offset(entt)]; - const auto pos = static_cast(traits_type::to_entity(ref)); - ENTT_ASSERT(packed[pos] == entt, "Invalid entity identifier"); + virtual basic_iterator try_emplace(const Entity entt, const bool force_back, const void * = nullptr) { + ENTT_ASSERT(!contains(entt), "Set already contains entity"); - packed[pos] = std::exchange(free_list, traits_type::construct(static_cast(pos))); - // lazy self-assignment guard - ref = null; + if(auto &elem = assure_at_least(entt); free_list == null || force_back) { + packed.push_back(entt); + elem = entity_traits::combine(static_cast(packed.size() - 1u), entity_traits::to_integral(entt)); + return begin(); + } else { + const auto pos = static_cast(entity_traits::to_entity(free_list)); + elem = entity_traits::combine(entity_traits::to_integral(free_list), entity_traits::to_integral(entt)); + free_list = std::exchange(packed[pos], entt); + return --(end() - pos); + } } public: /*! @brief Allocator type. */ - using allocator_type = typename alloc_traits::allocator_type; + using allocator_type = Allocator; /*! @brief Underlying entity identifier. */ - using entity_type = Entity; + using entity_type = typename entity_traits::value_type; + /*! @brief Underlying version type. */ + using version_type = typename entity_traits::version_type; /*! @brief Unsigned integer type. */ using size_type = std::size_t; /*! @brief Pointer type to contained entities. */ - using pointer = alloc_const_pointer; + using pointer = typename packed_container_type::const_pointer; /*! @brief Random access iterator type. */ - using iterator = sparse_set_iterator; + using iterator = basic_iterator; + /*! @brief Constant random access iterator type. */ + using const_iterator = iterator; /*! @brief Reverse iterator type. */ using reverse_iterator = std::reverse_iterator; + /*! @brief Constant reverse iterator type. */ + using const_reverse_iterator = reverse_iterator; + + /*! @brief Default constructor. */ + basic_sparse_set() + : basic_sparse_set{type_id()} {} + + /** + * @brief Constructs an empty container with a given allocator. + * @param allocator The allocator to use. + */ + explicit basic_sparse_set(const allocator_type &allocator) + : basic_sparse_set{type_id(), deletion_policy::swap_and_pop, allocator} {} /** * @brief Constructs an empty container with the given policy and allocator. * @param pol Type of deletion policy. - * @param alloc Allocator to use (possibly default-constructed). + * @param allocator The allocator to use (possibly default-constructed). */ - explicit basic_sparse_set(deletion_policy pol, const allocator_type &alloc = {}) - : allocator{alloc}, - bucket_allocator{alloc}, - sparse{bucket_alloc_traits::allocate(bucket_allocator, 0u)}, - packed{alloc_traits::allocate(allocator, 0u)}, - bucket{0u}, - count{0u}, - reserved{0u}, - free_list{tombstone}, - mode{pol} - {} + explicit basic_sparse_set(deletion_policy pol, const allocator_type &allocator = {}) + : basic_sparse_set{type_id(), pol, allocator} {} /** - * @brief Constructs an empty container with the given allocator. - * @param alloc Allocator to use (possibly default-constructed). + * @brief Constructs an empty container with the given value type, policy + * and allocator. + * @param value Returned value type, if any. + * @param pol Type of deletion policy. + * @param allocator The allocator to use (possibly default-constructed). */ - explicit basic_sparse_set(const allocator_type &alloc = {}) - : basic_sparse_set{deletion_policy::swap_and_pop, alloc} - {} + explicit basic_sparse_set(const type_info &value, deletion_policy pol = deletion_policy::swap_and_pop, const allocator_type &allocator = {}) + : sparse{allocator}, + packed{allocator}, + info{&value}, + free_list{tombstone}, + mode{pol} {} /** * @brief Move constructor. * @param other The instance to move from. */ - basic_sparse_set(basic_sparse_set &&other) ENTT_NOEXCEPT - : allocator{std::move(other.allocator)}, - bucket_allocator{std::move(other.bucket_allocator)}, - sparse{std::exchange(other.sparse, bucket_alloc_pointer{})}, - packed{std::exchange(other.packed, alloc_pointer{})}, - bucket{std::exchange(other.bucket, 0u)}, - count{std::exchange(other.count, 0u)}, - reserved{std::exchange(other.reserved, 0u)}, + basic_sparse_set(basic_sparse_set &&other) noexcept + : sparse{std::move(other.sparse)}, + packed{std::move(other.packed)}, + info{other.info}, free_list{std::exchange(other.free_list, tombstone)}, - mode{other.mode} - {} + mode{other.mode} {} + + /** + * @brief Allocator-extended move constructor. + * @param other The instance to move from. + * @param allocator The allocator to use. + */ + basic_sparse_set(basic_sparse_set &&other, const allocator_type &allocator) noexcept + : sparse{std::move(other.sparse), allocator}, + packed{std::move(other.packed), allocator}, + info{other.info}, + free_list{std::exchange(other.free_list, tombstone)}, + mode{other.mode} { + ENTT_ASSERT(alloc_traits::is_always_equal::value || packed.get_allocator() == other.packed.get_allocator(), "Copying a sparse set is not allowed"); + } /*! @brief Default destructor. */ virtual ~basic_sparse_set() { - release_memory(); + release_sparse_pages(); } /** @@ -338,38 +387,47 @@ public: * @param other The instance to move from. * @return This sparse set. */ - basic_sparse_set & operator=(basic_sparse_set &&other) ENTT_NOEXCEPT { - release_memory(); + basic_sparse_set &operator=(basic_sparse_set &&other) noexcept { + ENTT_ASSERT(alloc_traits::is_always_equal::value || packed.get_allocator() == other.packed.get_allocator(), "Copying a sparse set is not allowed"); - allocator = std::move(other.allocator); - bucket_allocator = std::move(other.bucket_allocator); - sparse = std::exchange(other.sparse, bucket_alloc_pointer{}); - packed = std::exchange(other.packed, alloc_pointer{}); - bucket = std::exchange(other.bucket, 0u); - count = std::exchange(other.count, 0u); - reserved = std::exchange(other.reserved, 0u); + release_sparse_pages(); + sparse = std::move(other.sparse); + packed = std::move(other.packed); + info = other.info; free_list = std::exchange(other.free_list, tombstone); mode = other.mode; - return *this; } + /** + * @brief Exchanges the contents with those of a given sparse set. + * @param other Sparse set to exchange the content with. + */ + void swap(basic_sparse_set &other) { + using std::swap; + swap(sparse, other.sparse); + swap(packed, other.packed); + swap(info, other.info); + swap(free_list, other.free_list); + swap(mode, other.mode); + } + + /** + * @brief Returns the associated allocator. + * @return The associated allocator. + */ + [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { + return packed.get_allocator(); + } + /** * @brief Returns the deletion policy of a sparse set. * @return The deletion policy of the sparse set. */ - [[nodiscard]] deletion_policy policy() const ENTT_NOEXCEPT { + [[nodiscard]] deletion_policy policy() const noexcept { return mode; } - /** - * @brief Returns the next slot available for insertion. - * @return The next slot available for insertion. - */ - [[nodiscard]] size_type slot() const ENTT_NOEXCEPT { - return free_list == null ? count : static_cast(traits_type::to_entity(free_list)); - } - /** * @brief Increases the capacity of a sparse set. * @@ -378,10 +436,8 @@ public: * * @param cap Desired capacity. */ - void reserve(const size_type cap) { - if(cap > reserved) { - resize_packed(cap); - } + virtual void reserve(const size_type cap) { + packed.reserve(cap); } /** @@ -389,15 +445,13 @@ public: * allocated space for. * @return Capacity of the sparse set. */ - [[nodiscard]] size_type capacity() const ENTT_NOEXCEPT { - return reserved; + [[nodiscard]] virtual size_type capacity() const noexcept { + return packed.capacity(); } /*! @brief Requests the removal of unused capacity. */ - void shrink_to_fit() { - if(count < reserved) { - resize_packed(count); - } + virtual void shrink_to_fit() { + packed.shrink_to_fit(); } /** @@ -410,8 +464,8 @@ public: * * @return Extent of the sparse set. */ - [[nodiscard]] size_type extent() const ENTT_NOEXCEPT { - return bucket * sparse_page; + [[nodiscard]] size_type extent() const noexcept { + return sparse.size() * entity_traits::page_size; } /** @@ -424,24 +478,24 @@ public: * * @return Number of elements. */ - [[nodiscard]] size_type size() const ENTT_NOEXCEPT { - return count; + [[nodiscard]] size_type size() const noexcept { + return packed.size(); } /** * @brief Checks whether a sparse set is empty. * @return True if the sparse set is empty, false otherwise. */ - [[nodiscard]] bool empty() const ENTT_NOEXCEPT { - return (count == size_type{}); + [[nodiscard]] bool empty() const noexcept { + return packed.empty(); } /** * @brief Direct access to the internal packed array. * @return A pointer to the internal packed array. */ - [[nodiscard]] pointer data() const ENTT_NOEXCEPT { - return packed; + [[nodiscard]] pointer data() const noexcept { + return packed.data(); } /** @@ -451,24 +505,35 @@ public: * array. If the sparse set is empty, the returned iterator will be equal to * `end()`. * - * @return An iterator to the first entity of the internal packed array. + * @return An iterator to the first entity of the sparse set. */ - [[nodiscard]] iterator begin() const ENTT_NOEXCEPT { - return iterator{std::addressof(packed), static_cast(count)}; + [[nodiscard]] const_iterator begin() const noexcept { + const auto pos = static_cast(packed.size()); + return iterator{packed, pos}; + } + + /*! @copydoc begin */ + [[nodiscard]] const_iterator cbegin() const noexcept { + return begin(); } /** * @brief Returns an iterator to the end. * * The returned iterator points to the element following the last entity in - * the internal packed array. Attempting to dereference the returned - * iterator results in undefined behavior. + * a sparse set. Attempting to dereference the returned iterator results in + * undefined behavior. * - * @return An iterator to the element following the last entity of the - * internal packed array. + * @return An iterator to the element following the last entity of a sparse + * set. */ - [[nodiscard]] iterator end() const ENTT_NOEXCEPT { - return iterator{std::addressof(packed), {}}; + [[nodiscard]] iterator end() const noexcept { + return iterator{packed, {}}; + } + + /*! @copydoc end */ + [[nodiscard]] const_iterator cend() const noexcept { + return end(); } /** @@ -481,44 +546,66 @@ public: * @return An iterator to the first entity of the reversed internal packed * array. */ - [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT { + [[nodiscard]] const_reverse_iterator rbegin() const noexcept { return std::make_reverse_iterator(end()); } + /*! @copydoc rbegin */ + [[nodiscard]] const_reverse_iterator crbegin() const noexcept { + return rbegin(); + } + /** * @brief Returns a reverse iterator to the end. * * The returned iterator points to the element following the last entity in - * the reversed internal packed array. Attempting to dereference the - * returned iterator results in undefined behavior. + * the reversed sparse set. Attempting to dereference the returned iterator + * results in undefined behavior. * * @return An iterator to the element following the last entity of the - * reversed internal packed array. + * reversed sparse set. */ - [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT { + [[nodiscard]] reverse_iterator rend() const noexcept { return std::make_reverse_iterator(begin()); } + /*! @copydoc rend */ + [[nodiscard]] const_reverse_iterator crend() const noexcept { + return rend(); + } + /** * @brief Finds an entity. - * @param entt A valid entity identifier. + * @param entt A valid identifier. * @return An iterator to the given entity if it's found, past the end * iterator otherwise. */ - [[nodiscard]] iterator find(const entity_type entt) const ENTT_NOEXCEPT { + [[nodiscard]] iterator find(const entity_type entt) const noexcept { return contains(entt) ? --(end() - index(entt)) : end(); } /** * @brief Checks if a sparse set contains an entity. - * @param entt A valid entity identifier. + * @param entt A valid identifier. * @return True if the sparse set contains the entity, false otherwise. */ - [[nodiscard]] bool contains(const entity_type entt) const ENTT_NOEXCEPT { - ENTT_ASSERT(entt != tombstone && entt != null, "Invalid entity"); - const auto curr = page(entt); + [[nodiscard]] bool contains(const entity_type entt) const noexcept { + const auto elem = sparse_ptr(entt); + constexpr auto cap = entity_traits::to_entity(null); // testing versions permits to avoid accessing the packed array - return (curr < bucket && sparse[curr] && sparse[curr][offset(entt)] != null); + return elem && (((~cap & entity_traits::to_integral(entt)) ^ entity_traits::to_integral(*elem)) < cap); + } + + /** + * @brief Returns the contained version for an identifier. + * @param entt A valid identifier. + * @return The version for the given identifier if present, the tombstone + * version otherwise. + */ + [[nodiscard]] version_type current(const entity_type entt) const noexcept { + const auto elem = sparse_ptr(entt); + constexpr auto fallback = entity_traits::to_version(tombstone); + return elem ? entity_traits::to_version(*elem) : fallback; } /** @@ -528,12 +615,12 @@ public: * Attempting to get the position of an entity that doesn't belong to the * sparse set results in undefined behavior. * - * @param entt A valid entity identifier. + * @param entt A valid identifier. * @return The position of the entity in the sparse set. */ - [[nodiscard]] size_type index(const entity_type entt) const ENTT_NOEXCEPT { + [[nodiscard]] size_type index(const entity_type entt) const noexcept { ENTT_ASSERT(contains(entt), "Set does not contain entity"); - return static_cast(traits_type::to_entity(sparse[page(entt)][offset(entt)])); + return static_cast(entity_traits::to_entity(sparse_ref(entt))); } /** @@ -541,8 +628,8 @@ public: * @param pos The position for which to return the entity. * @return The entity at specified location if any, a null entity otherwise. */ - [[nodiscard]] entity_type at(const size_type pos) const ENTT_NOEXCEPT { - return pos < count ? packed[pos] : null; + [[nodiscard]] entity_type at(const size_type pos) const noexcept { + return pos < packed.size() ? packed[pos] : null; } /** @@ -550,32 +637,28 @@ public: * @param pos The position for which to return the entity. * @return The entity at specified location. */ - [[nodiscard]] entity_type operator[](const size_type pos) const ENTT_NOEXCEPT { - ENTT_ASSERT(pos < count, "Position is out of bounds"); + [[nodiscard]] entity_type operator[](const size_type pos) const noexcept { + ENTT_ASSERT(pos < packed.size(), "Position is out of bounds"); return packed[pos]; } /** - * @brief Appends an entity to a sparse set. + * @brief Returns the element assigned to an entity, if any. * * @warning - * Attempting to assign an entity that already belongs to the sparse set - * results in undefined behavior. + * Attempting to use an entity that doesn't belong to the sparse set results + * in undefined behavior. * - * @param entt A valid entity identifier. - * @return The slot used for insertion. + * @param entt A valid identifier. + * @return An opaque pointer to the element assigned to the entity, if any. */ - size_type emplace_back(const entity_type entt) { - ENTT_ASSERT(!contains(entt), "Set already contains entity"); + [[nodiscard]] const void *get(const entity_type entt) const noexcept { + return get_at(index(entt)); + } - if(count == reserved) { - const size_type sz = static_cast(reserved * growth_factor); - resize_packed(sz + !(sz > reserved)); - } - - assure_page(page(entt))[offset(entt)] = traits_type::construct(static_cast(count)); - packed[count] = entt; - return count++; + /*! @copydoc get */ + [[nodiscard]] void *get(const entity_type entt) noexcept { + return const_cast(std::as_const(*this).get(entt)); } /** @@ -585,19 +668,29 @@ public: * Attempting to assign an entity that already belongs to the sparse set * results in undefined behavior. * - * @param entt A valid entity identifier. - * @return The slot used for insertion. + * @param entt A valid identifier. + * @param value Optional opaque value to forward to mixins, if any. + * @return Iterator pointing to the emplaced element in case of success, the + * `end()` iterator otherwise. */ - size_type emplace(const entity_type entt) { - if(free_list == null) { - return emplace_back(entt); - } else { - ENTT_ASSERT(!contains(entt), "Set already contains entity"); - const auto pos = static_cast(traits_type::to_entity(free_list)); - assure_page(page(entt))[offset(entt)] = traits_type::construct(static_cast(pos)); - free_list = std::exchange(packed[pos], entt); - return pos; - } + iterator emplace(const entity_type entt, const void *value = nullptr) { + return try_emplace(entt, false, value); + } + + /** + * @brief Bump the version number of an entity. + * + * @warning + * Attempting to bump the version of an entity that doesn't belong to the + * sparse set results in undefined behavior. + * + * @param entt A valid identifier. + */ + void bump(const entity_type entt) { + auto &entity = sparse_ref(entt); + ENTT_ASSERT(entt != tombstone && entity != null, "Cannot set the required version"); + entity = entity_traits::combine(entity_traits::to_integral(entity), entity_traits::to_integral(entt)); + packed[static_cast(entity_traits::to_entity(entity))] = entt; } /** @@ -610,17 +703,16 @@ public: * @tparam It Type of input iterator. * @param first An iterator to the first element of the range of entities. * @param last An iterator past the last element of the range of entities. + * @return Iterator pointing to the first element inserted in case of + * success, the `end()` iterator otherwise. */ template - void insert(It first, It last) { - reserve(count + std::distance(first, last)); - - for(; first != last; ++first) { - const auto entt = *first; - ENTT_ASSERT(!contains(entt), "Set already contains entity"); - assure_page(page(entt))[offset(entt)] = traits_type::construct(static_cast(count)); - packed[count++] = entt; + iterator insert(It first, It last) { + for(auto it = first; it != last; ++it) { + try_emplace(*it, true); } + + return first == last ? end() : find(*first); } /** @@ -630,12 +722,11 @@ public: * Attempting to erase an entity that doesn't belong to the sparse set * results in undefined behavior. * - * @param entt A valid entity identifier. - * @param ud Optional user data that are forwarded as-is to derived classes. + * @param entt A valid identifier. */ - void erase(const entity_type entt, void *ud = nullptr) { - ENTT_ASSERT(contains(entt), "Set does not contain entity"); - (mode == deletion_policy::in_place) ? in_place_pop(entt, ud) : swap_and_pop(entt, ud); + void erase(const entity_type entt) { + const auto it = --(end() - index(entt)); + pop(it, it + 1u); } /** @@ -646,23 +737,25 @@ public: * @tparam It Type of input iterator. * @param first An iterator to the first element of the range of entities. * @param last An iterator past the last element of the range of entities. - * @param ud Optional user data that are forwarded as-is to derived classes. */ template - void erase(It first, It last, void *ud = nullptr) { - for(; first != last; ++first) { - erase(*first, ud); + void erase(It first, It last) { + if constexpr(std::is_same_v) { + pop(first, last); + } else { + for(; first != last; ++first) { + erase(*first); + } } } /** * @brief Removes an entity from a sparse set if it exists. - * @param entt A valid entity identifier. - * @param ud Optional user data that are forwarded as-is to derived classes. + * @param entt A valid identifier. * @return True if the entity is actually removed, false otherwise. */ - bool remove(const entity_type entt, void *ud = nullptr) { - return contains(entt) && (erase(entt, ud), true); + bool remove(const entity_type entt) { + return contains(entt) && (erase(entt), true); } /** @@ -670,42 +763,45 @@ public: * @tparam It Type of input iterator. * @param first An iterator to the first element of the range of entities. * @param last An iterator past the last element of the range of entities. - * @param ud Optional user data that are forwarded as-is to derived classes. * @return The number of entities actually removed. */ template - size_type remove(It first, It last, void *ud = nullptr) { - size_type found{}; + size_type remove(It first, It last) { + size_type count{}; for(; first != last; ++first) { - found += remove(*first, ud); + count += remove(*first); } - return found; + return count; } /*! @brief Removes all tombstones from the packed array of a sparse set. */ void compact() { - size_type next = count; - for(; next && packed[next - 1u] == tombstone; --next); + size_type from = packed.size(); + for(; from && packed[from - 1u] == tombstone; --from) {} - for(auto *it = &free_list; *it != null && next; it = std::addressof(packed[traits_type::to_entity(*it)])) { - if(const size_type pos = traits_type::to_entity(*it); pos < next) { - --next; - move_and_pop(next, pos); - std::swap(packed[next], packed[pos]); - sparse[page(packed[pos])][offset(packed[pos])] = traits_type::construct(static_cast(pos)); - *it = traits_type::construct(static_cast(next)); - for(; next && packed[next - 1u] == tombstone; --next); + for(auto *it = &free_list; *it != null && from; it = std::addressof(packed[entity_traits::to_entity(*it)])) { + if(const size_type to = entity_traits::to_entity(*it); to < from) { + --from; + move_element(from, to); + + using std::swap; + swap(packed[from], packed[to]); + + const auto entity = static_cast(to); + sparse_ref(packed[to]) = entity_traits::combine(entity, entity_traits::to_integral(packed[to])); + *it = entity_traits::combine(static_cast(from), entity_traits::reserved); + for(; from && packed[from - 1u] == tombstone; --from) {} } } free_list = tombstone; - count = next; + packed.resize(from); } /** - * @copybrief swap_at + * @brief Swaps two entities in a sparse set. * * For what it's worth, this function affects both the internal sparse array * and the internal packed array. Users should not care of that anyway. @@ -714,23 +810,25 @@ public: * Attempting to swap entities that don't belong to the sparse set results * in undefined behavior. * - * @param lhs A valid entity identifier. - * @param rhs A valid entity identifier. + * @param lhs A valid identifier. + * @param rhs A valid identifier. */ - void swap(const entity_type lhs, const entity_type rhs) { - ENTT_ASSERT(contains(lhs), "Set does not contain entity"); - ENTT_ASSERT(contains(rhs), "Set does not contain entity"); + void swap_elements(const entity_type lhs, const entity_type rhs) { + ENTT_ASSERT(contains(lhs) && contains(rhs), "Set does not contain entities"); - auto &entt = sparse[page(lhs)][offset(lhs)]; - auto &other = sparse[page(rhs)][offset(rhs)]; + auto &entt = sparse_ref(lhs); + auto &other = sparse_ref(rhs); - const auto from = static_cast(traits_type::to_entity(entt)); - const auto to = static_cast(traits_type::to_entity(other)); + const auto from = entity_traits::to_entity(entt); + const auto to = entity_traits::to_entity(other); // basic no-leak guarantee (with invalid state) if swapping throws - swap_at(from, to); - std::swap(entt, other); - std::swap(packed[from], packed[to]); + swap_at(static_cast(from), static_cast(to)); + entt = entity_traits::combine(to, entity_traits::to_integral(packed[from])); + other = entity_traits::combine(from, entity_traits::to_integral(packed[to])); + + using std::swap; + swap(packed[from], packed[to]); } /** @@ -764,12 +862,11 @@ public: * @param args Arguments to forward to the sort function object, if any. */ template - void sort_n(const size_type length, Compare compare, Sort algo = Sort{}, Args &&... args) { - // basic no-leak guarantee (with invalid state) if sorting throws - ENTT_ASSERT(!(length > count), "Length exceeds the number of elements"); - compact(); + void sort_n(const size_type length, Compare compare, Sort algo = Sort{}, Args &&...args) { + ENTT_ASSERT(!(length > packed.size()), "Length exceeds the number of elements"); + ENTT_ASSERT(free_list == null, "Partial sorting with tombstones is not supported"); - algo(std::make_reverse_iterator(packed + length), std::make_reverse_iterator(packed), std::move(compare), std::forward(args)...); + algo(packed.rend() - length, packed.rend(), std::move(compare), std::forward(args)...); for(size_type pos{}; pos < length; ++pos) { auto curr = pos; @@ -780,7 +877,8 @@ public: const auto entt = packed[curr]; swap_at(next, idx); - sparse[page(entt)][offset(entt)] = traits_type::construct(static_cast(curr)); + const auto entity = static_cast(curr); + sparse_ref(entt) = entity_traits::combine(entity, entity_traits::to_integral(packed[curr])); curr = std::exchange(next, idx); } } @@ -799,8 +897,9 @@ public: * @param args Arguments to forward to the sort function object, if any. */ template - void sort(Compare compare, Sort algo = Sort{}, Args &&... args) { - sort_n(count, std::move(compare), std::move(algo), std::forward(args)...); + void sort(Compare compare, Sort algo = Sort{}, Args &&...args) { + compact(); + sort_n(packed.size(), std::move(compare), std::move(algo), std::forward(args)...); } /** @@ -824,11 +923,11 @@ public: const auto to = other.end(); auto from = other.begin(); - for(size_type pos = count - 1; pos && from != to; ++from) { + for(size_type pos = packed.size() - 1; pos && from != to; ++from) { if(contains(*from)) { if(*from != packed[pos]) { // basic no-leak guarantee (with invalid state) if swapping throws - swap(packed[pos], *from); + swap_elements(packed[pos], *from); } --pos; @@ -836,35 +935,42 @@ public: } } - /** - * @brief Clears a sparse set. - * @param ud Optional user data that are forwarded as-is to derived classes. - */ - void clear(void *ud = nullptr) { - for(auto &&entity: *this) { - if(entity != tombstone) { - in_place_pop(entity, ud); + /*! @brief Clears a sparse set. */ + void clear() { + if(const auto last = end(); free_list == null) { + pop(begin(), last); + } else { + for(auto &&entity: *this) { + // tombstone filter on itself + if(const auto it = find(entity); it != last) { + pop(it, it + 1u); + } } } free_list = tombstone; - count = 0u; + packed.clear(); } + /** + * @brief Returned value type, if any. + * @return Returned value type, if any. + */ + const type_info &type() const noexcept { + return *info; + } + + /*! @brief Forwards variables to derived classes, if any. */ + virtual void bind(any) noexcept {} + private: - typename alloc_traits::allocator_type allocator; - typename bucket_alloc_traits::allocator_type bucket_allocator; - bucket_alloc_pointer sparse; - alloc_pointer packed; - std::size_t bucket; - std::size_t count; - std::size_t reserved; + sparse_container_type sparse; + packed_container_type packed; + const type_info *info; entity_type free_list; deletion_policy mode; }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/entity/storage.hpp b/LiteLoader/third-party/include/entt/entity/storage.hpp index 5faf930..9bd6d11 100644 --- a/LiteLoader/third-party/include/entt/entity/storage.hpp +++ b/LiteLoader/third-party/include/entt/entity/storage.hpp @@ -1,39 +1,223 @@ #ifndef ENTT_ENTITY_STORAGE_HPP #define ENTT_ENTITY_STORAGE_HPP - #include #include #include #include #include #include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/algorithm.hpp" -#include "third-party/include/entt/core/fwd.hpp" -#include "third-party/include/entt/core/type_traits.hpp" -#include "third-party/include/entt/signal/sigh.hpp" +#include +#include "../config/config.h" +#include "../core/compressed_pair.hpp" +#include "../core/iterator.hpp" +#include "../core/memory.hpp" +#include "../core/type_info.hpp" #include "component.hpp" #include "entity.hpp" #include "fwd.hpp" #include "sparse_set.hpp" - +#include "storage_mixin.hpp" namespace entt { +/** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + +namespace internal { + +template +class storage_iterator final { + friend storage_iterator; + + using container_type = std::remove_const_t; + using alloc_traits = std::allocator_traits; + using comp_traits = component_traits>; + + using iterator_traits = std::iterator_traits, + typename alloc_traits::template rebind_traits::element_type>::const_pointer, + typename alloc_traits::template rebind_traits::element_type>::pointer>>; + +public: + using value_type = typename iterator_traits::value_type; + using pointer = typename iterator_traits::pointer; + using reference = typename iterator_traits::reference; + using difference_type = typename iterator_traits::difference_type; + using iterator_category = std::random_access_iterator_tag; + + constexpr storage_iterator() noexcept = default; + + constexpr storage_iterator(Container *ref, const difference_type idx) noexcept + : packed{ref}, + offset{idx} {} + + template, typename = std::enable_if_t> + constexpr storage_iterator(const storage_iterator> &other) noexcept + : storage_iterator{other.packed, other.offset} {} + + constexpr storage_iterator &operator++() noexcept { + return --offset, *this; + } + + constexpr storage_iterator operator++(int) noexcept { + storage_iterator orig = *this; + return ++(*this), orig; + } + + constexpr storage_iterator &operator--() noexcept { + return ++offset, *this; + } + + constexpr storage_iterator operator--(int) noexcept { + storage_iterator orig = *this; + return operator--(), orig; + } + + constexpr storage_iterator &operator+=(const difference_type value) noexcept { + offset -= value; + return *this; + } + + constexpr storage_iterator operator+(const difference_type value) const noexcept { + storage_iterator copy = *this; + return (copy += value); + } + + constexpr storage_iterator &operator-=(const difference_type value) noexcept { + return (*this += -value); + } + + constexpr storage_iterator operator-(const difference_type value) const noexcept { + return (*this + -value); + } + + [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept { + const auto pos = index() - value; + return (*packed)[pos / comp_traits::page_size][fast_mod(pos, comp_traits::page_size)]; + } + + [[nodiscard]] constexpr pointer operator->() const noexcept { + const auto pos = index(); + return (*packed)[pos / comp_traits::page_size] + fast_mod(pos, comp_traits::page_size); + } + + [[nodiscard]] constexpr reference operator*() const noexcept { + return *operator->(); + } + + [[nodiscard]] constexpr difference_type index() const noexcept { + return offset - 1; + } + +private: + Container *packed; + difference_type offset; +}; + +template +[[nodiscard]] constexpr std::ptrdiff_t operator-(const storage_iterator &lhs, const storage_iterator &rhs) noexcept { + return rhs.index() - lhs.index(); +} + +template +[[nodiscard]] constexpr bool operator==(const storage_iterator &lhs, const storage_iterator &rhs) noexcept { + return lhs.index() == rhs.index(); +} + +template +[[nodiscard]] constexpr bool operator!=(const storage_iterator &lhs, const storage_iterator &rhs) noexcept { + return !(lhs == rhs); +} + +template +[[nodiscard]] constexpr bool operator<(const storage_iterator &lhs, const storage_iterator &rhs) noexcept { + return lhs.index() > rhs.index(); +} + +template +[[nodiscard]] constexpr bool operator>(const storage_iterator &lhs, const storage_iterator &rhs) noexcept { + return lhs.index() < rhs.index(); +} + +template +[[nodiscard]] constexpr bool operator<=(const storage_iterator &lhs, const storage_iterator &rhs) noexcept { + return !(lhs > rhs); +} + +template +[[nodiscard]] constexpr bool operator>=(const storage_iterator &lhs, const storage_iterator &rhs) noexcept { + return !(lhs < rhs); +} + +template +class extended_storage_iterator final { + template + friend class extended_storage_iterator; + +public: + using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval()), std::forward_as_tuple(*std::declval()...))); + using pointer = input_iterator_pointer; + using reference = value_type; + using difference_type = std::ptrdiff_t; + using iterator_category = std::input_iterator_tag; + + constexpr extended_storage_iterator() + : it{} {} + + constexpr extended_storage_iterator(It base, Other... other) + : it{base, other...} {} + + template && ...) && (std::is_constructible_v && ...)>> + constexpr extended_storage_iterator(const extended_storage_iterator &other) + : it{other.it} {} + + constexpr extended_storage_iterator &operator++() noexcept { + return ++std::get(it), (++std::get(it), ...), *this; + } + + constexpr extended_storage_iterator operator++(int) noexcept { + extended_storage_iterator orig = *this; + return ++(*this), orig; + } + + [[nodiscard]] constexpr pointer operator->() const noexcept { + return operator*(); + } + + [[nodiscard]] constexpr reference operator*() const noexcept { + return {*std::get(it), *std::get(it)...}; + } + + template + friend constexpr bool operator==(const extended_storage_iterator &, const extended_storage_iterator &) noexcept; + +private: + std::tuple it; +}; + +template +[[nodiscard]] constexpr bool operator==(const extended_storage_iterator &lhs, const extended_storage_iterator &rhs) noexcept { + return std::get<0>(lhs.it) == std::get<0>(rhs.it); +} + +template +[[nodiscard]] constexpr bool operator!=(const extended_storage_iterator &lhs, const extended_storage_iterator &rhs) noexcept { + return !(lhs == rhs); +} + +} // namespace internal + +/** + * Internal details not to be documented. + * @endcond + */ /** * @brief Basic storage implementation. * - * This class is a refinement of a sparse set that associates an object to an - * entity. The main purpose of this class is to extend sparse sets to store - * components in a registry. It guarantees fast access both to the elements and - * to the entities. - * - * @note - * Entities and objects have the same order. - * - * @note * Internal data structures arrange elements to maximize performance. There are * no guarantees that objects are returned in the insertion order when iterate * a storage. Do not make assumption on the order in any case. @@ -42,256 +226,165 @@ namespace entt { * Empty types aren't explicitly instantiated. Therefore, many of the functions * normally available for non-empty types will not be available for empty ones. * - * @sa sparse_set - * - * @tparam Entity A valid entity type (see entt_traits for more details). * @tparam Type Type of objects assigned to the entities. + * @tparam Entity A valid entity type (see entt_traits for more details). * @tparam Allocator Type of allocator used to manage memory and elements. */ -template -class basic_storage_impl: public basic_sparse_set::template rebind_alloc> { - static constexpr auto packed_page = ENTT_PACKED_PAGE; - +template +class basic_storage: public basic_sparse_set::template rebind_alloc> { + using alloc_traits = std::allocator_traits; + static_assert(std::is_same_v, "Invalid value type"); + using underlying_type = basic_sparse_set>; + using container_type = std::vector>; using comp_traits = component_traits; - using underlying_type = basic_sparse_set::template rebind_alloc>; - using difference_type = typename entt_traits::difference_type; + static constexpr bool is_pinned_type_v = !(std::is_move_constructible_v && std::is_move_assignable_v); - using alloc_traits = typename std::allocator_traits::template rebind_traits; - using alloc_pointer = typename alloc_traits::pointer; - using alloc_const_pointer = typename alloc_traits::const_pointer; - - using bucket_alloc_traits = typename std::allocator_traits::template rebind_traits; - using bucket_alloc_pointer = typename bucket_alloc_traits::pointer; - - using bucket_alloc_const_type = typename std::allocator_traits::template rebind_alloc; - using bucket_alloc_const_pointer = typename std::allocator_traits::const_pointer; - - static_assert(alloc_traits::propagate_on_container_move_assignment::value); - static_assert(bucket_alloc_traits::propagate_on_container_move_assignment::value); - - template - struct storage_iterator final { - using difference_type = typename basic_storage_impl::difference_type; - using value_type = Value; - using pointer = value_type *; - using reference = value_type &; - using iterator_category = std::random_access_iterator_tag; - - storage_iterator() ENTT_NOEXCEPT = default; - - storage_iterator(bucket_alloc_pointer const *ref, const typename basic_storage_impl::difference_type idx) ENTT_NOEXCEPT - : packed{ref}, - index{idx} - {} - - storage_iterator & operator++() ENTT_NOEXCEPT { - return --index, *this; - } - - storage_iterator operator++(int) ENTT_NOEXCEPT { - storage_iterator orig = *this; - return ++(*this), orig; - } - - storage_iterator & operator--() ENTT_NOEXCEPT { - return ++index, *this; - } - - storage_iterator operator--(int) ENTT_NOEXCEPT { - storage_iterator orig = *this; - return operator--(), orig; - } - - storage_iterator & operator+=(const difference_type value) ENTT_NOEXCEPT { - index -= value; - return *this; - } - - storage_iterator operator+(const difference_type value) const ENTT_NOEXCEPT { - storage_iterator copy = *this; - return (copy += value); - } - - storage_iterator & operator-=(const difference_type value) ENTT_NOEXCEPT { - return (*this += -value); - } - - storage_iterator operator-(const difference_type value) const ENTT_NOEXCEPT { - return (*this + -value); - } - - difference_type operator-(const storage_iterator &other) const ENTT_NOEXCEPT { - return other.index - index; - } - - [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT { - const auto pos = size_type(index-value-1); - return (*packed)[page(pos)][offset(pos)]; - } - - [[nodiscard]] bool operator==(const storage_iterator &other) const ENTT_NOEXCEPT { - return other.index == index; - } - - [[nodiscard]] bool operator!=(const storage_iterator &other) const ENTT_NOEXCEPT { - return !(*this == other); - } - - [[nodiscard]] bool operator<(const storage_iterator &other) const ENTT_NOEXCEPT { - return index > other.index; - } - - [[nodiscard]] bool operator>(const storage_iterator &other) const ENTT_NOEXCEPT { - return index < other.index; - } - - [[nodiscard]] bool operator<=(const storage_iterator &other) const ENTT_NOEXCEPT { - return !(*this > other); - } - - [[nodiscard]] bool operator>=(const storage_iterator &other) const ENTT_NOEXCEPT { - return !(*this < other); - } - - [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT { - const auto pos = size_type(index-1u); - return std::addressof((*packed)[page(pos)][offset(pos)]); - } - - [[nodiscard]] reference operator*() const ENTT_NOEXCEPT { - return *operator->(); - } - - private: - bucket_alloc_pointer const *packed; - difference_type index; - }; - - [[nodiscard]] static auto page(const std::size_t pos) ENTT_NOEXCEPT { - return pos / packed_page; + [[nodiscard]] auto &element_at(const std::size_t pos) const { + return packed.first()[pos / comp_traits::page_size][fast_mod(pos, comp_traits::page_size)]; } - [[nodiscard]] static auto offset(const std::size_t pos) ENTT_NOEXCEPT { - return pos & (packed_page - 1); - } + auto assure_at_least(const std::size_t pos) { + auto &&container = packed.first(); + const auto idx = pos / comp_traits::page_size; - void release_memory() { - if(packed) { - // no-throw stable erase iteration - underlying_type::clear(); - - for(size_type pos{}; pos < bucket; ++pos) { - alloc_traits::deallocate(allocator, packed[pos], packed_page); - bucket_alloc_traits::destroy(bucket_allocator, std::addressof(packed[pos])); - } - - bucket_alloc_traits::deallocate(bucket_allocator, packed, bucket); - } - } - - void assure_at_least(const std::size_t last) { - if(const auto idx = page(last - 1u); !(idx < bucket)) { - const size_type sz = idx + 1u; - const auto mem = bucket_alloc_traits::allocate(bucket_allocator, sz); - std::uninitialized_copy(packed, packed + bucket, mem); - size_type pos{}; + if(!(idx < container.size())) { + auto curr = container.size(); + container.resize(idx + 1u, nullptr); ENTT_TRY { - for(pos = bucket; pos < sz; ++pos) { - auto pg = alloc_traits::allocate(allocator, packed_page); - bucket_alloc_traits::construct(bucket_allocator, std::addressof(mem[pos]), pg); + for(const auto last = container.size(); curr < last; ++curr) { + container[curr] = alloc_traits::allocate(packed.second(), comp_traits::page_size); } - } ENTT_CATCH { - for(auto next = bucket; next < pos; ++next) { - alloc_traits::deallocate(allocator, mem[next], packed_page); - } - - std::destroy(mem, mem + pos); - bucket_alloc_traits::deallocate(bucket_allocator, mem, sz); + } + ENTT_CATCH { + container.resize(curr); ENTT_THROW; } - - std::destroy(packed, packed + bucket); - bucket_alloc_traits::deallocate(bucket_allocator, packed, bucket); - - packed = mem; - bucket = sz; } - } - void release_unused_pages() { - if(const auto length = underlying_type::size() / packed_page; length < bucket) { - const auto mem = bucket_alloc_traits::allocate(bucket_allocator, length); - std::uninitialized_copy(packed, packed + length, mem); - - for(auto pos = length; pos < bucket; ++pos) { - alloc_traits::deallocate(allocator, packed[pos], packed_page); - bucket_alloc_traits::destroy(bucket_allocator, std::addressof(packed[pos])); - } - - bucket_alloc_traits::deallocate(bucket_allocator, packed, bucket); - - packed = mem; - bucket = length; - } + return container[idx] + fast_mod(pos, comp_traits::page_size); } template - auto & push_at(const std::size_t pos, Args &&... args) { - ENTT_ASSERT(pos < (bucket * packed_page), "Out of bounds index"); - auto *instance = std::addressof(packed[page(pos)][offset(pos)]); + auto emplace_element(const Entity entt, const bool force_back, Args &&...args) { + const auto it = base_type::try_emplace(entt, force_back); - if constexpr(std::is_aggregate_v) { - alloc_traits::construct(allocator, instance, Type{std::forward(args)...}); - } else { - alloc_traits::construct(allocator, instance, std::forward(args)...); + ENTT_TRY { + auto elem = assure_at_least(static_cast(it.index())); + entt::uninitialized_construct_using_allocator(to_address(elem), packed.second(), std::forward(args)...); + } + ENTT_CATCH { + base_type::pop(it, it + 1u); + ENTT_THROW; } - return *instance; + return it; } - void pop_at(const std::size_t pos) { - alloc_traits::destroy(allocator, std::addressof(packed[page(pos)][offset(pos)])); + void shrink_to_size(const std::size_t sz) { + for(auto pos = sz, length = base_type::size(); pos < length; ++pos) { + if constexpr(comp_traits::in_place_delete) { + if(base_type::at(pos) != tombstone) { + std::destroy_at(std::addressof(element_at(pos))); + } + } else { + std::destroy_at(std::addressof(element_at(pos))); + } + } + + auto &&container = packed.first(); + auto page_allocator{packed.second()}; + const auto from = (sz + comp_traits::page_size - 1u) / comp_traits::page_size; + + for(auto pos = from, last = container.size(); pos < last; ++pos) { + alloc_traits::deallocate(page_allocator, container[pos], comp_traits::page_size); + } + + container.resize(from); + } + +private: + const void *get_at(const std::size_t pos) const final { + return std::addressof(element_at(pos)); + } + + void swap_at([[maybe_unused]] const std::size_t lhs, [[maybe_unused]] const std::size_t rhs) final { + // use a runtime value to avoid compile-time suppression that drives the code coverage tool crazy + ENTT_ASSERT((lhs + 1u) && !is_pinned_type_v, "Pinned type"); + + if constexpr(!is_pinned_type_v) { + using std::swap; + swap(element_at(lhs), element_at(rhs)); + } + } + + void move_element([[maybe_unused]] const std::size_t from, [[maybe_unused]] const std::size_t to) final { + // use a runtime value to avoid compile-time suppression that drives the code coverage tool crazy + ENTT_ASSERT((from + 1u) && !is_pinned_type_v, "Pinned type"); + + if constexpr(!is_pinned_type_v) { + auto &elem = element_at(from); + entt::uninitialized_construct_using_allocator(to_address(assure_at_least(to)), packed.second(), std::move(elem)); + std::destroy_at(std::addressof(elem)); + } } protected: - /*! @copydoc basic_sparse_set::swap_at */ - void swap_at(const std::size_t lhs, const std::size_t rhs) final { - std::swap(packed[page(lhs)][offset(lhs)], packed[page(rhs)][offset(rhs)]); + /*! @brief Random access iterator type. */ + using basic_iterator = typename underlying_type::basic_iterator; + + /** + * @brief Erases entities from a sparse set. + * @param first An iterator to the first element of the range of entities. + * @param last An iterator past the last element of the range of entities. + */ + void pop(basic_iterator first, basic_iterator last) override { + for(; first != last; ++first) { + // cannot use first.index() because it would break with cross iterators + auto &elem = element_at(base_type::index(*first)); + + if constexpr(comp_traits::in_place_delete) { + base_type::in_place_pop(first); + std::destroy_at(std::addressof(elem)); + } else { + auto &other = element_at(base_type::size() - 1u); + // destroying on exit allows reentrant destructors + [[maybe_unused]] auto unused = std::exchange(elem, std::move(other)); + std::destroy_at(std::addressof(other)); + base_type::swap_and_pop(first); + } + } } - /*! @copydoc basic_sparse_set::move_and_pop */ - void move_and_pop(const std::size_t from, const std::size_t to) final { - push_at(to, std::move(packed[page(from)][offset(from)])); - pop_at(from); - } - - /*! @copydoc basic_sparse_set::swap_and_pop */ - void swap_and_pop(const Entity entt, void *ud) override { - const auto pos = underlying_type::index(entt); - const auto last = underlying_type::size() - 1u; - auto &&elem = packed[page(pos)][offset(pos)]; - - // support for nosy destructors - [[maybe_unused]] auto unused = std::move(elem); - elem = std::move(packed[page(last)][offset(last)]); - pop_at(last); - - underlying_type::swap_and_pop(entt, ud); - } - - /*! @copydoc basic_sparse_set::in_place_pop */ - void in_place_pop(const Entity entt, void *ud) override { - const auto pos = underlying_type::index(entt); - underlying_type::in_place_pop(entt, ud); - // support for nosy destructors - pop_at(pos); + /** + * @brief Assigns an entity to a storage. + * @param entt A valid identifier. + * @param value Optional opaque value. + * @param force_back Force back insertion. + * @return Iterator pointing to the emplaced element. + */ + basic_iterator try_emplace([[maybe_unused]] const Entity entt, const bool force_back, const void *value) override { + if(value) { + if constexpr(std::is_copy_constructible_v) { + return emplace_element(entt, force_back, *static_cast(value)); + } else { + return base_type::end(); + } + } else { + if constexpr(std::is_default_constructible_v) { + return emplace_element(entt, force_back); + } else { + return base_type::end(); + } + } } public: + /*! @brief Base type. */ + using base_type = underlying_type; /*! @brief Allocator type. */ - using allocator_type = typename alloc_traits::allocator_type; + using allocator_type = Allocator; /*! @brief Type of the objects assigned to entities. */ using value_type = Type; /*! @brief Underlying entity identifier. */ @@ -299,65 +392,92 @@ public: /*! @brief Unsigned integer type. */ using size_type = std::size_t; /*! @brief Pointer type to contained elements. */ - using pointer = bucket_alloc_pointer; + using pointer = typename container_type::pointer; /*! @brief Constant pointer type to contained elements. */ - using const_pointer = bucket_alloc_const_pointer; + using const_pointer = typename alloc_traits::template rebind_traits::const_pointer; /*! @brief Random access iterator type. */ - using iterator = storage_iterator; + using iterator = internal::storage_iterator; /*! @brief Constant random access iterator type. */ - using const_iterator = storage_iterator; + using const_iterator = internal::storage_iterator; /*! @brief Reverse iterator type. */ using reverse_iterator = std::reverse_iterator; /*! @brief Constant reverse iterator type. */ using const_reverse_iterator = std::reverse_iterator; + /*! @brief Extended iterable storage proxy. */ + using iterable = iterable_adaptor>; + /*! @brief Constant extended iterable storage proxy. */ + using const_iterable = iterable_adaptor>; + + /*! @brief Default constructor. */ + basic_storage() + : basic_storage{allocator_type{}} {} /** - * @brief Default constructor. - * @param alloc Allocator to use (possibly default-constructed). + * @brief Constructs an empty storage with a given allocator. + * @param allocator The allocator to use. */ - explicit basic_storage_impl(const allocator_type &alloc = {}) - : underlying_type{deletion_policy{comp_traits::in_place_delete::value}, alloc}, - allocator{alloc}, - bucket_allocator{alloc}, - packed{bucket_alloc_traits::allocate(bucket_allocator, 0u)}, - bucket{} - {} + explicit basic_storage(const allocator_type &allocator) + : base_type{type_id(), deletion_policy{comp_traits::in_place_delete}, allocator}, + packed{container_type{allocator}, allocator} {} /** * @brief Move constructor. * @param other The instance to move from. */ - basic_storage_impl(basic_storage_impl &&other) ENTT_NOEXCEPT - : underlying_type{std::move(other)}, - allocator{std::move(other.allocator)}, - bucket_allocator{std::move(other.bucket_allocator)}, - packed{std::exchange(other.packed, bucket_alloc_pointer{})}, - bucket{std::exchange(other.bucket, 0u)} - {} + basic_storage(basic_storage &&other) noexcept + : base_type{std::move(other)}, + packed{std::move(other.packed)} {} + + /** + * @brief Allocator-extended move constructor. + * @param other The instance to move from. + * @param allocator The allocator to use. + */ + basic_storage(basic_storage &&other, const allocator_type &allocator) noexcept + : base_type{std::move(other), allocator}, + packed{container_type{std::move(other.packed.first()), allocator}, allocator} { + ENTT_ASSERT(alloc_traits::is_always_equal::value || packed.second() == other.packed.second(), "Copying a storage is not allowed"); + } /*! @brief Default destructor. */ - ~basic_storage_impl() override { - release_memory(); + ~basic_storage() override { + shrink_to_size(0u); } /** * @brief Move assignment operator. * @param other The instance to move from. - * @return This sparse set. + * @return This storage. */ - basic_storage_impl & operator=(basic_storage_impl &&other) ENTT_NOEXCEPT { - release_memory(); - - underlying_type::operator=(std::move(other)); - - allocator = std::move(other.allocator); - bucket_allocator = std::move(other.bucket_allocator); - packed = std::exchange(other.packed, bucket_alloc_pointer{}); - bucket = std::exchange(other.bucket, 0u); + basic_storage &operator=(basic_storage &&other) noexcept { + ENTT_ASSERT(alloc_traits::is_always_equal::value || packed.second() == other.packed.second(), "Copying a storage is not allowed"); + shrink_to_size(0u); + base_type::operator=(std::move(other)); + packed.first() = std::move(other.packed.first()); + propagate_on_container_move_assignment(packed.second(), other.packed.second()); return *this; } + /** + * @brief Exchanges the contents with those of a given storage. + * @param other Storage to exchange the content with. + */ + void swap(basic_storage &other) { + using std::swap; + underlying_type::swap(other); + propagate_on_container_swap(packed.second(), other.packed.second()); + swap(packed.first(), other.packed.first()); + } + + /** + * @brief Returns the associated allocator. + * @return The associated allocator. + */ + [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { + return allocator_type{packed.second()}; + } + /** * @brief Increases the capacity of a storage. * @@ -366,11 +486,10 @@ public: * * @param cap Desired capacity. */ - void reserve(const size_type cap) { - underlying_type::reserve(cap); - - if(cap > underlying_type::size()) { - assure_at_least(cap); + void reserve(const size_type cap) override { + if(cap != 0u) { + base_type::reserve(cap); + assure_at_least(cap - 1u); } } @@ -379,27 +498,27 @@ public: * allocated space for. * @return Capacity of the storage. */ - [[nodiscard]] size_type capacity() const ENTT_NOEXCEPT { - return bucket * packed_page; + [[nodiscard]] size_type capacity() const noexcept override { + return packed.first().size() * comp_traits::page_size; } /*! @brief Requests the removal of unused capacity. */ - void shrink_to_fit() { - underlying_type::shrink_to_fit(); - release_unused_pages(); + void shrink_to_fit() override { + base_type::shrink_to_fit(); + shrink_to_size(base_type::size()); } /** * @brief Direct access to the array of objects. * @return A pointer to the array of objects. */ - [[nodiscard]] const_pointer raw() const ENTT_NOEXCEPT { - return packed; + [[nodiscard]] const_pointer raw() const noexcept { + return packed.first().data(); } /*! @copydoc raw */ - [[nodiscard]] pointer raw() ENTT_NOEXCEPT { - return packed; + [[nodiscard]] pointer raw() noexcept { + return packed.first().data(); } /** @@ -410,20 +529,20 @@ public: * * @return An iterator to the first instance of the internal array. */ - [[nodiscard]] const_iterator cbegin() const ENTT_NOEXCEPT { - const difference_type pos = underlying_type::size(); - return const_iterator{std::addressof(packed), pos}; + [[nodiscard]] const_iterator cbegin() const noexcept { + const auto pos = static_cast(base_type::size()); + return const_iterator{&packed.first(), pos}; } /*! @copydoc cbegin */ - [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT { + [[nodiscard]] const_iterator begin() const noexcept { return cbegin(); } /*! @copydoc begin */ - [[nodiscard]] iterator begin() ENTT_NOEXCEPT { - const difference_type pos = underlying_type::size(); - return iterator{std::addressof(packed), pos}; + [[nodiscard]] iterator begin() noexcept { + const auto pos = static_cast(base_type::size()); + return iterator{&packed.first(), pos}; } /** @@ -436,18 +555,18 @@ public: * @return An iterator to the element following the last instance of the * internal array. */ - [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT { - return const_iterator{std::addressof(packed), {}}; + [[nodiscard]] const_iterator cend() const noexcept { + return const_iterator{&packed.first(), {}}; } /*! @copydoc cend */ - [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT { + [[nodiscard]] const_iterator end() const noexcept { return cend(); } /*! @copydoc end */ - [[nodiscard]] iterator end() ENTT_NOEXCEPT { - return iterator{std::addressof(packed), {}}; + [[nodiscard]] iterator end() noexcept { + return iterator{&packed.first(), {}}; } /** @@ -459,17 +578,17 @@ public: * * @return An iterator to the first instance of the reversed internal array. */ - [[nodiscard]] const_reverse_iterator crbegin() const ENTT_NOEXCEPT { + [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return std::make_reverse_iterator(cend()); } /*! @copydoc crbegin */ - [[nodiscard]] const_reverse_iterator rbegin() const ENTT_NOEXCEPT { + [[nodiscard]] const_reverse_iterator rbegin() const noexcept { return crbegin(); } /*! @copydoc rbegin */ - [[nodiscard]] reverse_iterator rbegin() ENTT_NOEXCEPT { + [[nodiscard]] reverse_iterator rbegin() noexcept { return std::make_reverse_iterator(end()); } @@ -483,17 +602,17 @@ public: * @return An iterator to the element following the last instance of the * reversed internal array. */ - [[nodiscard]] const_reverse_iterator crend() const ENTT_NOEXCEPT { + [[nodiscard]] const_reverse_iterator crend() const noexcept { return std::make_reverse_iterator(cbegin()); } /*! @copydoc crend */ - [[nodiscard]] const_reverse_iterator rend() const ENTT_NOEXCEPT { + [[nodiscard]] const_reverse_iterator rend() const noexcept { return crend(); } /*! @copydoc rend */ - [[nodiscard]] reverse_iterator rend() ENTT_NOEXCEPT { + [[nodiscard]] reverse_iterator rend() noexcept { return std::make_reverse_iterator(begin()); } @@ -504,64 +623,66 @@ public: * Attempting to use an entity that doesn't belong to the storage results in * undefined behavior. * - * @param entt A valid entity identifier. + * @param entt A valid identifier. * @return The object assigned to the entity. */ - [[nodiscard]] const value_type & get(const entity_type entt) const ENTT_NOEXCEPT { - const auto idx = underlying_type::index(entt); - return packed[page(idx)][offset(idx)]; + [[nodiscard]] const value_type &get(const entity_type entt) const noexcept { + return element_at(base_type::index(entt)); } /*! @copydoc get */ - [[nodiscard]] value_type & get(const entity_type entt) ENTT_NOEXCEPT { + [[nodiscard]] value_type &get(const entity_type entt) noexcept { return const_cast(std::as_const(*this).get(entt)); } + /** + * @brief Returns the object assigned to an entity as a tuple. + * @param entt A valid identifier. + * @return The object assigned to the entity as a tuple. + */ + [[nodiscard]] std::tuple get_as_tuple(const entity_type entt) const noexcept { + return std::forward_as_tuple(get(entt)); + } + + /*! @copydoc get_as_tuple */ + [[nodiscard]] std::tuple get_as_tuple(const entity_type entt) noexcept { + return std::forward_as_tuple(get(entt)); + } + /** * @brief Assigns an entity to a storage and constructs its object. * - * This version accept both types that can be constructed in place directly - * and types like aggregates that do not work well with a placement new as - * performed usually under the hood during an _emplace back_. - * * @warning * Attempting to use an entity that already belongs to the storage results * in undefined behavior. * * @tparam Args Types of arguments to use to construct the object. - * @param entt A valid entity identifier. + * @param entt A valid identifier. * @param args Parameters to use to construct an object for the entity. * @return A reference to the newly created object. */ template - value_type & emplace(const entity_type entt, Args &&... args) { - const auto pos = underlying_type::slot(); - assure_at_least(pos + 1u); - - auto &value = push_at(pos, std::forward(args)...); - - ENTT_TRY { - [[maybe_unused]] const auto curr = underlying_type::emplace(entt); - ENTT_ASSERT(pos == curr, "Misplaced component"); - } ENTT_CATCH { - pop_at(pos); - ENTT_THROW; + value_type &emplace(const entity_type entt, Args &&...args) { + if constexpr(std::is_aggregate_v) { + const auto it = emplace_element(entt, false, Type{std::forward(args)...}); + return element_at(static_cast(it.index())); + } else { + const auto it = emplace_element(entt, false, std::forward(args)...); + return element_at(static_cast(it.index())); } - - return value; } /** * @brief Updates the instance assigned to a given entity in-place. * @tparam Func Types of the function objects to invoke. - * @param entt A valid entity identifier. + * @param entt A valid identifier. * @param func Valid function objects. * @return A reference to the updated instance. */ template - decltype(auto) patch(const entity_type entt, Func &&... func) { - const auto idx = underlying_type::index(entt); - auto &&elem = packed[page(idx)][offset(idx)]; + value_type &patch(const entity_type entt, Func &&...func) { + const auto idx = base_type::index(entt); + auto &elem = element_at(idx); (std::forward(func)(elem), ...); return elem; } @@ -581,19 +702,8 @@ public: */ template void insert(It first, It last, const value_type &value = {}) { - const auto cap = underlying_type::size() + std::distance(first, last); - underlying_type::reserve(cap); - assure_at_least(cap); - for(; first != last; ++first) { - push_at(underlying_type::size(), value); - - ENTT_TRY { - underlying_type::emplace_back(*first); - } ENTT_CATCH { - pop_at(underlying_type::size()); - ENTT_THROW; - } + emplace_element(*first, true, value); } } @@ -609,134 +719,125 @@ public: * @param last An iterator past the last element of the range of entities. * @param from An iterator to the first element of the range of objects. */ - template::value_type>, value_type>>> + template::value_type, value_type>>> void insert(EIt first, EIt last, CIt from) { - const auto cap = underlying_type::size() + std::distance(first, last); - underlying_type::reserve(cap); - assure_at_least(cap); - for(; first != last; ++first, ++from) { - push_at(underlying_type::size(), *from); - - ENTT_TRY { - underlying_type::emplace_back(*first); - } ENTT_CATCH { - pop_at(underlying_type::size()); - ENTT_THROW; - } + emplace_element(*first, true, *from); } } /** - * @brief Sort elements according to the given comparison function. + * @brief Returns an iterable object to use to _visit_ a storage. * - * The comparison function object must return `true` if the first element - * is _less_ than the second one, `false` otherwise. The signature of the - * comparison function should be equivalent to one of the following: + * The iterable object returns a tuple that contains the current entity and + * a reference to its component. * - * @code{.cpp} - * bool(const Entity, const Entity); - * bool(const Type &, const Type &); - * @endcode - * - * Moreover, the comparison function object shall induce a - * _strict weak ordering_ on the values. - * - * The sort function oject must offer a member function template - * `operator()` that accepts three arguments: - * - * * An iterator to the first element of the range to sort. - * * An iterator past the last element of the range to sort. - * * A comparison function to use to compare the elements. - * - * @warning - * Empty types are never instantiated. Therefore, only comparison function - * objects that require to return entities rather than components are - * accepted. - * - * @tparam Compare Type of comparison function object. - * @tparam Sort Type of sort function object. - * @tparam Args Types of arguments to forward to the sort function object. - * @param length Number of elements to sort. - * @param compare A valid comparison function object. - * @param algo A valid sort function object. - * @param args Arguments to forward to the sort function object, if any. + * @return An iterable object to use to _visit_ the storage. */ - template - void sort_n(const size_type length, Compare compare, Sort algo = Sort{}, Args &&... args) { - if constexpr(std::is_invocable_v) { - underlying_type::sort_n(length, [this, compare = std::move(compare)](const auto lhs, const auto rhs) { - const auto ilhs = underlying_type::index(lhs), irhs = underlying_type::index(rhs); - return compare(std::as_const(packed[page(ilhs)][offset(ilhs)]), std::as_const(packed[page(irhs)][offset(irhs)])); - }, std::move(algo), std::forward(args)...); - } else { - underlying_type::sort_n(length, std::move(compare), std::move(algo), std::forward(args)...); - } + [[nodiscard]] iterable each() noexcept { + return {internal::extended_storage_iterator{base_type::begin(), begin()}, internal::extended_storage_iterator{base_type::end(), end()}}; } - /** - * @brief Sort all elements according to the given comparison function. - * - * @sa sort_n - * - * @tparam Compare Type of comparison function object. - * @tparam Sort Type of sort function object. - * @tparam Args Types of arguments to forward to the sort function object. - * @param compare A valid comparison function object. - * @param algo A valid sort function object. - * @param args Arguments to forward to the sort function object, if any. - */ - template - void sort(Compare compare, Sort algo = Sort{}, Args &&... args) { - sort_n(underlying_type::size(), std::move(compare), std::move(algo), std::forward(args)...); + /*! @copydoc each */ + [[nodiscard]] const_iterable each() const noexcept { + return {internal::extended_storage_iterator{base_type::cbegin(), cbegin()}, internal::extended_storage_iterator{base_type::cend(), cend()}}; } private: - typename alloc_traits::allocator_type allocator; - typename bucket_alloc_traits::allocator_type bucket_allocator; - bucket_alloc_pointer packed; - size_type bucket; + compressed_pair packed; }; - -/*! @copydoc basic_storage_impl */ -template -class basic_storage_impl::ignore_if_empty::value && std::is_empty_v>> - : public basic_sparse_set::template rebind_alloc> -{ +/*! @copydoc basic_storage */ +template +class basic_storage>> + : public basic_sparse_set::template rebind_alloc> { + using alloc_traits = std::allocator_traits; + static_assert(std::is_same_v, "Invalid value type"); + using underlying_type = basic_sparse_set>; using comp_traits = component_traits; - using underlying_type = basic_sparse_set::template rebind_alloc>; - using alloc_traits = typename std::allocator_traits::template rebind_traits; public: + /*! @brief Base type. */ + using base_type = underlying_type; /*! @brief Allocator type. */ - using allocator_type = typename alloc_traits::allocator_type; + using allocator_type = Allocator; /*! @brief Type of the objects assigned to entities. */ using value_type = Type; /*! @brief Underlying entity identifier. */ using entity_type = Entity; /*! @brief Unsigned integer type. */ using size_type = std::size_t; + /*! @brief Extended iterable storage proxy. */ + using iterable = iterable_adaptor>; + /*! @brief Constant extended iterable storage proxy. */ + using const_iterable = iterable_adaptor>; + + /*! @brief Default constructor. */ + basic_storage() + : basic_storage{allocator_type{}} {} /** - * @brief Default constructor. - * @param alloc Allocator to use (possibly default-constructed). + * @brief Constructs an empty container with a given allocator. + * @param allocator The allocator to use. */ - explicit basic_storage_impl(const allocator_type &alloc = {}) - : underlying_type{deletion_policy{comp_traits::in_place_delete::value}, alloc} - {} + explicit basic_storage(const allocator_type &allocator) + : base_type{type_id(), deletion_policy{comp_traits::in_place_delete}, allocator} {} /** - * @brief Fake get function. + * @brief Move constructor. + * @param other The instance to move from. + */ + basic_storage(basic_storage &&other) noexcept = default; + + /** + * @brief Allocator-extended move constructor. + * @param other The instance to move from. + * @param allocator The allocator to use. + */ + basic_storage(basic_storage &&other, const allocator_type &allocator) noexcept + : base_type{std::move(other), allocator} {} + + /** + * @brief Move assignment operator. + * @param other The instance to move from. + * @return This storage. + */ + basic_storage &operator=(basic_storage &&other) noexcept = default; + + /** + * @brief Returns the associated allocator. + * @return The associated allocator. + */ + [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { + return allocator_type{base_type::get_allocator()}; + } + + /** + * @brief Returns the object assigned to an entity, that is `void`. * * @warning * Attempting to use an entity that doesn't belong to the storage results in * undefined behavior. * - * @param entt A valid entity identifier. + * @param entt A valid identifier. */ - void get([[maybe_unused]] const entity_type entt) const ENTT_NOEXCEPT { - ENTT_ASSERT(underlying_type::contains(entt), "Storage does not contain entity"); + void get([[maybe_unused]] const entity_type entt) const noexcept { + ENTT_ASSERT(base_type::contains(entt), "Storage does not contain entity"); + } + + /** + * @brief Returns an empty tuple. + * + * @warning + * Attempting to use an entity that doesn't belong to the storage results in + * undefined behavior. + * + * @param entt A valid identifier. + * @return Returns an empty tuple. + */ + [[nodiscard]] std::tuple<> get_as_tuple([[maybe_unused]] const entity_type entt) const noexcept { + ENTT_ASSERT(base_type::contains(entt), "Storage does not contain entity"); + return std::tuple{}; } /** @@ -747,299 +848,94 @@ public: * in undefined behavior. * * @tparam Args Types of arguments to use to construct the object. - * @param entt A valid entity identifier. - * @param args Parameters to use to construct an object for the entity. + * @param entt A valid identifier. */ template - void emplace(const entity_type entt, Args &&... args) { - [[maybe_unused]] value_type instance{std::forward(args)...}; - underlying_type::emplace(entt); + void emplace(const entity_type entt, Args &&...) { + base_type::try_emplace(entt, false); } /** - * @brief Updates the instance assigned to a given entity in-place. - * @tparam Func Types of the function objects to invoke. - * @param entt A valid entity identifier. - * @param func Valid function objects. - */ + * @brief Updates the instance assigned to a given entity in-place. + * @tparam Func Types of the function objects to invoke. + * @param entt A valid identifier. + * @param func Valid function objects. + */ template - void patch([[maybe_unused]] const entity_type entt, Func &&... func) { - ENTT_ASSERT(underlying_type::contains(entt), "Storage does not contain entity"); + void patch([[maybe_unused]] const entity_type entt, Func &&...func) { + ENTT_ASSERT(base_type::contains(entt), "Storage does not contain entity"); (std::forward(func)(), ...); } - /** - * @brief Assigns one or more entities to a storage. - * - * @warning - * Attempting to assign an entity that already belongs to the storage - * results in undefined behavior. - * - * @tparam It Type of input iterator. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - */ - template - void insert(It first, It last, const value_type & = {}) { - underlying_type::insert(first, last); - } -}; - - -/** - * @brief Mixin type to use to wrap basic storage classes. - * @tparam Type The type of the underlying storage. - */ -template -struct storage_adapter_mixin: Type { - static_assert(std::is_same_v>, "Invalid object type"); - - /*! @brief Type of the objects assigned to entities. */ - using value_type = typename Type::value_type; - /*! @brief Underlying entity identifier. */ - using entity_type = typename Type::entity_type; - - /*! @brief Inherited constructors. */ - using Type::Type; - - /** - * @brief Assigns entities to a storage. - * @tparam Args Types of arguments to use to construct the object. - * @param entt A valid entity identifier. - * @param args Parameters to use to initialize the object. - * @return A reference to the newly created object. - */ - template - decltype(auto) emplace(basic_registry &, const entity_type entt, Args &&... args) { - return Type::emplace(entt, std::forward(args)...); - } - /** * @brief Assigns entities to a storage. * @tparam It Type of input iterator. - * @tparam Args Types of arguments to use to construct the objects assigned - * to the entities. + * @tparam Args Types of optional arguments. * @param first An iterator to the first element of the range of entities. * @param last An iterator past the last element of the range of entities. - * @param args Parameters to use to initialize the objects assigned to the - * entities. */ template - void insert(basic_registry &, It first, It last, Args &&... args) { - Type::insert(first, last, std::forward(args)...); - } - - /** - * @brief Patches the given instance for an entity. - * @tparam Func Types of the function objects to invoke. - * @param entt A valid entity identifier. - * @param func Valid function objects. - * @return A reference to the patched instance. - */ - template - decltype(auto) patch(basic_registry &, const entity_type entt, Func &&... func) { - return Type::patch(entt, std::forward(func)...); - } -}; - - -/** - * @brief Mixin type to use to add signal support to storage types. - * @tparam Type The type of the underlying storage. - */ -template -class sigh_storage_mixin final: public Type { - /*! @copydoc basic_sparse_set::swap_and_pop */ - void swap_and_pop(const typename Type::entity_type entt, void *ud) final { - ENTT_ASSERT(ud != nullptr, "Invalid pointer to registry"); - destruction.publish(*static_cast *>(ud), entt); - Type::swap_and_pop(entt, ud); - } - - /*! @copydoc basic_sparse_set::in_place_pop */ - void in_place_pop(const typename Type::entity_type entt, void *ud) final { - ENTT_ASSERT(ud != nullptr, "Invalid pointer to registry"); - destruction.publish(*static_cast *>(ud), entt); - Type::in_place_pop(entt, ud); - } - -public: - /*! @brief Underlying value type. */ - using value_type = typename Type::value_type; - /*! @brief Underlying entity identifier. */ - using entity_type = typename Type::entity_type; - - /*! @brief Inherited constructors. */ - using Type::Type; - - /** - * @brief Returns a sink object. - * - * The sink returned by this function can be used to receive notifications - * whenever a new instance is created and assigned to an entity.
- * The function type for a listener is equivalent to: - * - * @code{.cpp} - * void(basic_registry &, entity_type); - * @endcode - * - * Listeners are invoked **after** the object has been assigned to the - * entity. - * - * @sa sink - * - * @return A temporary sink object. - */ - [[nodiscard]] auto on_construct() ENTT_NOEXCEPT { - return sink{construction}; - } - - /** - * @brief Returns a sink object. - * - * The sink returned by this function can be used to receive notifications - * whenever an instance is explicitly updated.
- * The function type for a listener is equivalent to: - * - * @code{.cpp} - * void(basic_registry &, entity_type); - * @endcode - * - * Listeners are invoked **after** the object has been updated. - * - * @sa sink - * - * @return A temporary sink object. - */ - [[nodiscard]] auto on_update() ENTT_NOEXCEPT { - return sink{update}; - } - - /** - * @brief Returns a sink object. - * - * The sink returned by this function can be used to receive notifications - * whenever an instance is removed from an entity and thus destroyed.
- * The function type for a listener is equivalent to: - * - * @code{.cpp} - * void(basic_registry &, entity_type); - * @endcode - * - * Listeners are invoked **before** the object has been removed from the - * entity. - * - * @sa sink - * - * @return A temporary sink object. - */ - [[nodiscard]] auto on_destroy() ENTT_NOEXCEPT { - return sink{destruction}; - } - - /** - * @brief Assigns entities to a storage. - * @tparam Args Types of arguments to use to construct the object. - * @param owner The registry that issued the request. - * @param entt A valid entity identifier. - * @param args Parameters to use to initialize the object. - * @return A reference to the newly created object. - */ - template - decltype(auto) emplace(basic_registry &owner, const entity_type entt, Args &&... args) { - Type::emplace(entt, std::forward(args)...); - construction.publish(owner, entt); - return this->get(entt); - } - - /** - * @brief Assigns entities to a storage. - * @tparam It Type of input iterator. - * @tparam Args Types of arguments to use to construct the objects assigned - * to the entities. - * @param owner The registry that issued the request. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - * @param args Parameters to use to initialize the objects assigned to the - * entities. - */ - template - void insert(basic_registry &owner, It first, It last, Args &&... args) { - Type::insert(first, last, std::forward(args)...); - - if(!construction.empty()) { - for(; first != last; ++first) { - construction.publish(owner, *first); - } + void insert(It first, It last, Args &&...) { + for(; first != last; ++first) { + base_type::try_emplace(*first, true); } } /** - * @brief Patches the given instance for an entity. - * @tparam Func Types of the function objects to invoke. - * @param owner The registry that issued the request. - * @param entt A valid entity identifier. - * @param func Valid function objects. - * @return A reference to the patched instance. + * @brief Returns an iterable object to use to _visit_ a storage. + * + * The iterable object returns a tuple that contains the current entity. + * + * @return An iterable object to use to _visit_ the storage. */ - template - decltype(auto) patch(basic_registry &owner, const entity_type entt, Func &&... func) { - Type::patch(entt, std::forward(func)...); - update.publish(owner, entt); - return this->get(entt); + [[nodiscard]] iterable each() noexcept { + return {internal::extended_storage_iterator{base_type::begin()}, internal::extended_storage_iterator{base_type::end()}}; } -private: - sigh &, const entity_type)> construction{}; - sigh &, const entity_type)> destruction{}; - sigh &, const entity_type)> update{}; + /*! @copydoc each */ + [[nodiscard]] const_iterable each() const noexcept { + return {internal::extended_storage_iterator{base_type::cbegin()}, internal::extended_storage_iterator{base_type::cend()}}; + } }; - /** - * @brief Storage implementation dispatcher. + * @brief Provides a common way to define storage types. + * @tparam Type Storage value type. * @tparam Entity A valid entity type (see entt_traits for more details). - * @tparam Type Type of objects assigned to the entities. * @tparam Allocator Type of allocator used to manage memory and elements. */ -template -struct basic_storage: basic_storage_impl { - using basic_storage_impl::basic_storage_impl; +template +struct storage_type { + /*! @brief Type-to-storage conversion result. */ + using type = sigh_storage_mixin>; }; +/** + * @brief Helper type. + * @tparam Args Arguments to forward. + */ +template +using storage_type_t = typename storage_type::type; /** - * @brief Provides a common way to access certain properties of storage types. + * Type-to-storage conversion utility that preserves constness. + * @tparam Type Storage value type, eventually const. * @tparam Entity A valid entity type (see entt_traits for more details). - * @tparam Type Type of objects managed by the storage class. + * @tparam Allocator Type of allocator used to manage memory and elements. */ -template -struct storage_traits { - /*! @brief Resulting type after component-to-storage conversion. */ - using storage_type = sigh_storage_mixin>; +template +struct storage_for { + /*! @brief Type-to-storage conversion result. */ + using type = constness_as_t, Entity, Allocator>, Type>; }; - /** - * @brief Gets the element assigned to an entity from a storage, if any. - * @tparam Type Storage type. - * @param container A valid instance of a storage class. - * @param entt A valid entity identifier. - * @return A possibly empty tuple containing the requested element. + * @brief Helper type. + * @tparam Args Arguments to forward. */ -template -[[nodiscard]] auto get_as_tuple([[maybe_unused]] Type &container, [[maybe_unused]] const typename Type::entity_type entt) { - static_assert(std::is_same_v, typename storage_traits::storage_type>, "Invalid storage"); - - if constexpr(std::is_void_v) { - return std::make_tuple(); - } else { - return std::forward_as_tuple(container.get(entt)); - } -} - - -} +template +using storage_for_t = typename storage_for::type; +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/entity/utility.hpp b/LiteLoader/third-party/include/entt/entity/utility.hpp index e109e8d..84c2b3c 100644 --- a/LiteLoader/third-party/include/entt/entity/utility.hpp +++ b/LiteLoader/third-party/include/entt/entity/utility.hpp @@ -2,7 +2,7 @@ #define ENTT_ENTITY_UTILITY_HPP -#include "third-party/include/entt/core/type_traits.hpp" +#include "../core/type_traits.hpp" namespace entt { diff --git a/LiteLoader/third-party/include/entt/entity/view.hpp b/LiteLoader/third-party/include/entt/entity/view.hpp index 6413bb3..5c732ed 100644 --- a/LiteLoader/third-party/include/entt/entity/view.hpp +++ b/LiteLoader/third-party/include/entt/entity/view.hpp @@ -1,387 +1,343 @@ #ifndef ENTT_ENTITY_VIEW_HPP #define ENTT_ENTITY_VIEW_HPP - -#include #include +#include #include -#include -#include #include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/type_traits.hpp" +#include +#include "../config/config.h" +#include "../core/iterator.hpp" +#include "../core/type_traits.hpp" #include "component.hpp" #include "entity.hpp" #include "fwd.hpp" #include "sparse_set.hpp" #include "storage.hpp" -#include "utility.hpp" - namespace entt { - /** * @cond TURN_OFF_DOXYGEN * Internal details not to be documented. */ - namespace internal { - -template +template class view_iterator final { - using basic_common_type = basic_sparse_set::value_type>; + using iterator_type = typename Type::const_iterator; - [[nodiscard]] bool valid() const { - const auto entt = *it; - return Policy::accept(entt) - && std::apply([entt](const auto *... curr) { return (curr->contains(entt) && ...); }, pools) - && std::apply([entt](const auto *... curr) { return (!curr->contains(entt) && ...); }, filter); + [[nodiscard]] bool valid() const noexcept { + return ((Get != 0u) || (*it != tombstone)) + && std::apply([entt = *it](const auto *...curr) { return (curr->contains(entt) && ...); }, pools) + && std::apply([entt = *it](const auto *...curr) { return (!curr->contains(entt) && ...); }, filter); } public: - using iterator_type = It; - using difference_type = typename std::iterator_traits::difference_type; - using value_type = typename std::iterator_traits::value_type; - using pointer = typename std::iterator_traits::pointer; - using reference = typename std::iterator_traits::reference; - using iterator_category = std::bidirectional_iterator_tag; + using value_type = typename iterator_type::value_type; + using pointer = typename iterator_type::pointer; + using reference = typename iterator_type::reference; + using difference_type = typename iterator_type::difference_type; + using iterator_category = std::forward_iterator_tag; - view_iterator() ENTT_NOEXCEPT - : first{}, + constexpr view_iterator() noexcept + : it{}, last{}, - it{}, pools{}, - filter{} - {} + filter{} {} - view_iterator(It from, It to, It curr, std::array all_of, std::array none_of) ENTT_NOEXCEPT - : first{from}, + view_iterator(iterator_type curr, iterator_type to, std::array all_of, std::array none_of) noexcept + : it{curr}, last{to}, - it{curr}, pools{all_of}, - filter{none_of} - { - if(it != last && !valid()) { - ++(*this); + filter{none_of} { + while(it != last && !valid()) { + ++it; } } - view_iterator & operator++() ENTT_NOEXCEPT { - while(++it != last && !valid()); + view_iterator &operator++() noexcept { + while(++it != last && !valid()) {} return *this; } - view_iterator operator++(int) ENTT_NOEXCEPT { + view_iterator operator++(int) noexcept { view_iterator orig = *this; return ++(*this), orig; } - view_iterator & operator--() ENTT_NOEXCEPT { - while(--it != first && !valid()); - return *this; - } - - view_iterator operator--(int) ENTT_NOEXCEPT { - view_iterator orig = *this; - return operator--(), orig; - } - - [[nodiscard]] bool operator==(const view_iterator &other) const ENTT_NOEXCEPT { - return other.it == it; - } - - [[nodiscard]] bool operator!=(const view_iterator &other) const ENTT_NOEXCEPT { - return !(*this == other); - } - - [[nodiscard]] pointer operator->() const { + [[nodiscard]] pointer operator->() const noexcept { return &*it; } - [[nodiscard]] reference operator*() const { + [[nodiscard]] reference operator*() const noexcept { return *operator->(); } + template + friend constexpr bool operator==(const view_iterator &, const view_iterator &) noexcept; + private: - It first; - It last; - It it; - std::array pools; - std::array filter; + iterator_type it; + iterator_type last; + std::array pools; + std::array filter; }; - +template +[[nodiscard]] constexpr bool operator==(const view_iterator &lhs, const view_iterator &rhs) noexcept { + return lhs.it == rhs.it; } +template +[[nodiscard]] constexpr bool operator!=(const view_iterator &lhs, const view_iterator &rhs) noexcept { + return !(lhs == rhs); +} + +template +struct extended_view_iterator final { + using difference_type = std::ptrdiff_t; + using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval()), std::declval().get_as_tuple({})...)); + using pointer = input_iterator_pointer; + using reference = value_type; + using iterator_category = std::input_iterator_tag; + + constexpr extended_view_iterator() + : it{}, + pools{} {} + + extended_view_iterator(It from, std::tuple storage) + : it{from}, + pools{storage} {} + + extended_view_iterator &operator++() noexcept { + return ++it, *this; + } + + extended_view_iterator operator++(int) noexcept { + extended_view_iterator orig = *this; + return ++(*this), orig; + } + + [[nodiscard]] reference operator*() const noexcept { + return std::apply([entt = *it](auto *...curr) { return std::tuple_cat(std::make_tuple(entt), curr->get_as_tuple(entt)...); }, pools); + } + + [[nodiscard]] pointer operator->() const noexcept { + return operator*(); + } + + template + friend bool constexpr operator==(const extended_view_iterator &, const extended_view_iterator &) noexcept; + +private: + It it; + std::tuple pools; +}; + +template +[[nodiscard]] constexpr bool operator==(const extended_view_iterator &lhs, const extended_view_iterator &rhs) noexcept { + return lhs.it == rhs.it; +} + +template +[[nodiscard]] constexpr bool operator!=(const extended_view_iterator &lhs, const extended_view_iterator &rhs) noexcept { + return !(lhs == rhs); +} + +} // namespace internal /** * Internal details not to be documented. * @endcond */ - -/*! @brief Stable storage policy, aimed at pointer stability. */ -struct stable_storage_policy { - /** - * @cond TURN_OFF_DOXYGEN - * Internal details not to be documented. - */ - template - [[nodiscard]] static constexpr bool accept(const Entity entity) ENTT_NOEXCEPT { - return entity != tombstone; - } - /** - * Internal details not to be documented. - * @endcond - */ -}; - - -/*! @brief Packed storage policy, aimed at faster linear iteration. */ -struct packed_storage_policy { - /** - * @cond TURN_OFF_DOXYGEN - * Internal details not to be documented. - */ - template - [[nodiscard]] static constexpr bool accept(const Entity) ENTT_NOEXCEPT { - return true; - } - /** - * Internal details not to be documented. - * @endcond - */ -}; - - /** * @brief View implementation. * * Primary template isn't defined on purpose. All the specializations give a * compile-time error, but for a few reasonable cases. */ -template -class basic_view_impl; - - -/*! @brief View implementation dispatcher. */ -template -struct basic_view; - +template +class basic_view; /** * @brief Multi component view. * - * Multi component views iterate over those entities that have at least all the - * given components in their bags. During initialization, a multi component view - * looks at the number of entities available for each component and uses the - * smallest set in order to get a performance boost when iterate. + * Multi component views iterate over those entities that are at least in the + * given storage. During initialization, a multi component view looks at the + * number of entities available for each component and uses the smallest set in + * order to get a performance boost when iterating. * * @b Important * * Iterators aren't invalidated if: * - * * New instances of the given components are created and assigned to entities. - * * The entity currently pointed is modified (as an example, if one of the - * given components is removed from the entity to which the iterator points). + * * New elements are added to the storage. + * * The entity currently pointed is modified (for example, components are added + * or removed from it). * * The entity currently pointed is destroyed. * * In all other cases, modifying the pools iterated by the view in any way * invalidates all the iterators and using them results in undefined behavior. * - * @note - * Views share references to the underlying data structures of the registry that - * generated them. Therefore any change to the entities and to the components - * made by means of the registry are immediately reflected by views. - * - * @warning - * Lifetime of a view must not overcome that of the registry that generated it. - * In any other case, attempting to use a view results in undefined behavior. - * - * @tparam Policy Common (stricter) storage policy. - * @tparam Entity A valid entity type (see entt_traits for more details). - * @tparam Exclude Types of components used to filter the view. - * @tparam Component Types of components iterated by the view. + * @tparam Get Types of storage iterated by the view. + * @tparam Exclude Types of storage used to filter the view. */ -template -class basic_view_impl, Component...> { - using basic_common_type = basic_sparse_set; +template +class basic_view, exclude_t> { + using underlying_type = std::common_type_t; + using basic_common_type = std::common_type_t; - template - using storage_type = constness_as_t>::storage_type, Comp>; + template + friend class basic_view; - class iterable final { - template - struct iterable_iterator final { - using difference_type = std::ptrdiff_t; - using value_type = decltype(std::tuple_cat(std::tuple{}, std::declval().get({}))); - using pointer = void; - using reference = value_type; - using iterator_category = std::input_iterator_tag; + template + static constexpr std::size_t index_of = type_list_index_v, type_list>; - iterable_iterator(It from, const basic_view_impl *parent) ENTT_NOEXCEPT - : it{from}, - view{parent} - {} - - iterable_iterator & operator++() ENTT_NOEXCEPT { - return ++it, *this; - } - - iterable_iterator operator++(int) ENTT_NOEXCEPT { - iterable_iterator orig = *this; - return ++(*this), orig; - } - - [[nodiscard]] reference operator*() const ENTT_NOEXCEPT { - return std::tuple_cat(std::make_tuple(*it), view->get(*it)); - } - - [[nodiscard]] bool operator==(const iterable_iterator &other) const ENTT_NOEXCEPT { - return other.it == it; - } - - [[nodiscard]] bool operator!=(const iterable_iterator &other) const ENTT_NOEXCEPT { - return !(*this == other); - } - - private: - It it; - const basic_view_impl *view; - }; - - public: - using iterator = iterable_iterator>; - using reverse_iterator = iterable_iterator>; - - iterable(const basic_view_impl &parent) - : view{parent} - {} - - [[nodiscard]] iterator begin() const ENTT_NOEXCEPT { - return { view.begin(), &view }; - } - - [[nodiscard]] iterator end() const ENTT_NOEXCEPT { - return { view.end(), &view }; - } - - [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT { - return { view.rbegin(), &view }; - } - - [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT { - return { view.rend(), &view }; - } - - private: - const basic_view_impl view; - }; - - [[nodiscard]] const auto * candidate() const ENTT_NOEXCEPT { - return (std::min)({ static_cast(std::get *>(pools))... }, [](const auto *lhs, const auto *rhs) { - return lhs->size() < rhs->size(); - }); - } - - [[nodiscard]] auto pools_to_unchecked_array() const ENTT_NOEXCEPT { - std::size_t pos{}; - std::array other{}; - (static_cast(std::get *>(pools) == view ? void() : void(other[pos++] = std::get *>(pools))), ...); + [[nodiscard]] auto opaque_check_set() const noexcept { + std::array other{}; + std::apply([&other, pos = 0u, view = view](const auto *...curr) mutable { ((curr == view ? void() : void(other[pos++] = curr)), ...); }, pools); return other; } - [[nodiscard]] auto filter_to_array() const ENTT_NOEXCEPT { - return std::array{std::get *>(filter)...}; + [[nodiscard]] auto filter_as_array() const noexcept { + return std::apply([](const auto *...curr) { return std::array{curr...}; }, filter); } - template - [[nodiscard]] auto dispatch_get([[maybe_unused]] It &it, [[maybe_unused]] const Entity entt) const { - if constexpr(std::is_same_v::value_type, typename storage_type::value_type>) { - return std::forward_as_tuple(*it); + template + [[nodiscard]] auto dispatch_get(const std::tuple &curr) const { + if constexpr(Curr == Other) { + return std::forward_as_tuple(std::get(curr)...); } else { - return get_as_tuple(*std::get *>(pools), entt); + return storage().get_as_tuple(std::get<0>(curr)); } } - template - void traverse(Func func) const { - if constexpr(std::is_void_v *>(pools)->get({}))>) { - for(const auto entt: static_cast(*std::get *>(pools))) { - if(Policy::accept(entt) && ((std::is_same_v || std::get *>(pools)->contains(entt)) && ...) - && (!std::get *>(filter)->contains(entt) && ...)) - { - if constexpr(is_applicable_v{}, std::declval().get({})))>) { - std::apply(func, std::tuple_cat(std::make_tuple(entt), get(entt))); - } else { - std::apply(func, get(entt)); - } - } - } - } else { - auto it = std::get *>(pools)->begin(); + [[nodiscard]] auto reject(const underlying_type entt) const noexcept { + return std::apply([entt](const auto *...curr) { return (curr->contains(entt) || ...); }, filter); + } - for(const auto entt: static_cast(*std::get *>(pools))) { - if(Policy::accept(entt) && ((std::is_same_v || std::get *>(pools)->contains(entt)) && ...) - && (!std::get *>(filter)->contains(entt) && ...)) - { - if constexpr(is_applicable_v{}, std::declval().get({})))>) { - std::apply(func, std::tuple_cat(std::make_tuple(entt), dispatch_get(it, entt)...)); - } else { - std::apply(func, std::tuple_cat(dispatch_get(it, entt)...)); - } + template + void each(Func &func, std::index_sequence) const { + for(const auto curr: storage().each()) { + if(const auto entt = std::get<0>(curr); ((sizeof...(Get) != 1u) || (entt != tombstone)) && ((Curr == Index || storage().contains(entt)) && ...) && !reject(entt)) { + if constexpr(is_applicable_v{}, std::declval().get({})))>) { + std::apply(func, std::tuple_cat(std::make_tuple(entt), dispatch_get(curr)...)); + } else { + std::apply(func, std::tuple_cat(dispatch_get(curr)...)); } - - ++it; } } } + template + void pick_and_each(Func &func, std::index_sequence seq) const { + ((&storage() == view ? each(func, seq) : void()), ...); + } + public: /*! @brief Underlying entity identifier. */ - using entity_type = Entity; + using entity_type = underlying_type; /*! @brief Unsigned integer type. */ using size_type = std::size_t; + /*! @brief Common type among all storage types. */ + using base_type = basic_common_type; /*! @brief Bidirectional iterator type. */ - using iterator = internal::view_iterator; - /*! @brief Reverse iterator type. */ - using reverse_iterator = internal::view_iterator; + using iterator = internal::view_iterator; /*! @brief Iterable view type. */ - using iterable_view = iterable; + using iterable = iterable_adaptor>; /*! @brief Default constructor to use to create empty, invalid views. */ - basic_view_impl() ENTT_NOEXCEPT - : view{} - {} + basic_view() noexcept + : pools{}, + filter{}, + view{} {} /** * @brief Constructs a multi-type view from a set of storage classes. - * @param component The storage for the types to iterate. - * @param epool The storage for the types used to filter the view. + * @param value The storage for the types to iterate. + * @param exclude The storage for the types used to filter the view. */ - basic_view_impl(storage_type &... component, const storage_type &... epool) ENTT_NOEXCEPT - : pools{&component...}, - filter{&epool...}, - view{candidate()} - {} + basic_view(Get &...value, Exclude &...exclude) noexcept + : pools{&value...}, + filter{&exclude...}, + view{[](const base_type *first, const auto *...other) { ((first = other->size() < first->size() ? other : first), ...); return first; }(&value...)} {} /** - * @brief Forces the type to use to drive iterations. - * @tparam Comp Type of component to use to drive the iteration. + * @brief Constructs a multi-type view from a set of storage classes. + * @param value The storage for the types to iterate. + * @param exclude The storage for the types used to filter the view. */ - template - void use() const ENTT_NOEXCEPT { - view = std::get *>(pools); + basic_view(std::tuple value, std::tuple exclude = {}) noexcept + : pools{std::apply([](auto &...curr) { return std::make_tuple(&curr...); }, value)}, + filter{std::apply([](auto &...curr) { return std::make_tuple(&curr...); }, exclude)}, + view{std::apply([](const base_type *first, const auto *...other) { ((first = other->size() < first->size() ? other : first), ...); return first; }, pools)} {} + + /** + * @brief Creates a new view driven by a given component in its iterations. + * @tparam Type Type of component used to drive the iteration. + * @return A new view driven by the given component in its iterations. + */ + template + [[nodiscard]] basic_view use() const noexcept { + return use>(); + } + + /** + * @brief Creates a new view driven by a given component in its iterations. + * @tparam Index Index of the component used to drive the iteration. + * @return A new view driven by the given component in its iterations. + */ + template + [[nodiscard]] basic_view use() const noexcept { + basic_view other{*this}; + other.view = &storage(); + return other; + } + + /** + * @brief Updates the internal leading view if required. + * @return A newly created and internally optimized view. + */ + [[nodiscard]] basic_view refresh() const noexcept { + return std::apply([](auto *...elem) { return basic_view{*elem...}; }, std::tuple_cat(pools, filter)); + } + + /** + * @brief Returns the leading storage of a view. + * @return The leading storage of the view. + */ + [[nodiscard]] const base_type &handle() const noexcept { + return *view; + } + + /** + * @brief Returns the storage for a given component type. + * @tparam Comp Type of component of which to return the storage. + * @return The storage for the given component type. + */ + template + [[nodiscard]] decltype(auto) storage() const noexcept { + return storage>(); + } + + /** + * @brief Returns the storage for a given index. + * @tparam Index Index of the storage to return. + * @return The storage for the given index. + */ + template + [[nodiscard]] decltype(auto) storage() const noexcept { + return *std::get(pools); } /** * @brief Estimates the number of entities iterated by the view. * @return Estimated number of entities iterated by the view. */ - [[nodiscard]] size_type size_hint() const ENTT_NOEXCEPT { + [[nodiscard]] size_type size_hint() const noexcept { return view->size(); } @@ -393,8 +349,8 @@ public: * * @return An iterator to the first entity of the view. */ - [[nodiscard]] iterator begin() const { - return iterator{view->begin(), view->end(), view->begin(), pools_to_unchecked_array(), filter_to_array()}; + [[nodiscard]] iterator begin() const noexcept { + return iterator{view->begin(), view->end(), opaque_check_set(), filter_as_array()}; } /** @@ -406,35 +362,8 @@ public: * * @return An iterator to the entity following the last entity of the view. */ - [[nodiscard]] iterator end() const { - return iterator{view->begin(), view->end(), view->end(), pools_to_unchecked_array(), filter_to_array()}; - } - - /** - * @brief Returns an iterator to the first entity of the reversed view. - * - * The returned iterator points to the first entity of the reversed view. If - * the view is empty, the returned iterator will be equal to `rend()`. - * - * @return An iterator to the first entity of the reversed view. - */ - [[nodiscard]] reverse_iterator rbegin() const { - return reverse_iterator{view->rbegin(), view->rend(), view->rbegin(), pools_to_unchecked_array(), filter_to_array()}; - } - - /** - * @brief Returns an iterator that is past the last entity of the reversed - * view. - * - * The returned iterator points to the entity following the last entity of - * the reversed view. Attempting to dereference the returned iterator - * results in undefined behavior. - * - * @return An iterator to the entity following the last entity of the - * reversed view. - */ - [[nodiscard]] reverse_iterator rend() const { - return reverse_iterator{view->rbegin(), view->rend(), view->rend(), pools_to_unchecked_array(), filter_to_array()}; + [[nodiscard]] iterator end() const noexcept { + return iterator{view->end(), view->end(), opaque_check_set(), filter_as_array()}; } /** @@ -442,7 +371,7 @@ public: * @return The first entity of the view if one exists, the null entity * otherwise. */ - [[nodiscard]] entity_type front() const { + [[nodiscard]] entity_type front() const noexcept { const auto it = begin(); return it != end() ? *it : null; } @@ -452,64 +381,89 @@ public: * @return The last entity of the view if one exists, the null entity * otherwise. */ - [[nodiscard]] entity_type back() const { - const auto it = rbegin(); - return it != rend() ? *it : null; + [[nodiscard]] entity_type back() const noexcept { + auto it = view->rbegin(); + for(const auto last = view->rend(); it != last && !contains(*it); ++it) {} + return it == view->rend() ? null : *it; } /** * @brief Finds an entity. - * @param entt A valid entity identifier. + * @param entt A valid identifier. * @return An iterator to the given entity if it's found, past the end * iterator otherwise. */ - [[nodiscard]] iterator find(const entity_type entt) const { - const auto it = iterator{view->begin(), view->end(), view->find(entt), pools_to_unchecked_array(), filter_to_array()}; - return (it != end() && *it == entt) ? it : end(); + [[nodiscard]] iterator find(const entity_type entt) const noexcept { + return contains(entt) ? iterator{view->find(entt), view->end(), opaque_check_set(), filter_as_array()} : end(); + } + + /** + * @brief Returns the components assigned to the given entity. + * @param entt A valid identifier. + * @return The components assigned to the given entity. + */ + [[nodiscard]] decltype(auto) operator[](const entity_type entt) const { + return get(entt); } /** * @brief Checks if a view is properly initialized. * @return True if the view is properly initialized, false otherwise. */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { + [[nodiscard]] explicit operator bool() const noexcept { return view != nullptr; } /** * @brief Checks if a view contains an entity. - * @param entt A valid entity identifier. + * @param entt A valid identifier. * @return True if the view contains the given entity, false otherwise. */ - [[nodiscard]] bool contains(const entity_type entt) const { - return (std::get *>(pools)->contains(entt) && ...) && (!std::get *>(filter)->contains(entt) && ...); + [[nodiscard]] bool contains(const entity_type entt) const noexcept { + return std::apply([entt](const auto *...curr) { return (curr->contains(entt) && ...); }, pools) + && std::apply([entt](const auto *...curr) { return (!curr->contains(entt) && ...); }, filter); } /** * @brief Returns the components assigned to the given entity. * - * Prefer this function instead of `registry::get` during iterations. It has - * far better performance than its counterpart. - * * @warning - * Attempting to use an invalid component type results in a compilation - * error. Attempting to use an entity that doesn't belong to the view - * results in undefined behavior. + * Attempting to use an entity that doesn't belong to the view results in + * undefined behavior. * - * @tparam Comp Types of components to get. - * @param entt A valid entity identifier. + * @tparam Type Types of components to get. + * @param entt A valid identifier. * @return The components assigned to the entity. */ - template - [[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entt) const { - ENTT_ASSERT(contains(entt), "View does not contain entity"); - - if constexpr(sizeof...(Comp) == 0) { - return std::tuple_cat(get_as_tuple(*std::get *>(pools), entt)...); - } else if constexpr(sizeof...(Comp) == 1) { - return (std::get *>(pools)->get(entt), ...); + template + [[nodiscard]] decltype(auto) get(const entity_type entt) const { + if constexpr(sizeof...(Type) == 0) { + return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, pools); + } else if constexpr(sizeof...(Type) == 1) { + return (storage>().get(entt), ...); } else { - return std::tuple_cat(get_as_tuple(*std::get *>(pools), entt)...); + return std::tuple_cat(storage>().get_as_tuple(entt)...); + } + } + + /** + * @brief Returns the components assigned to the given entity. + * + * @warning + * Attempting to use an entity that doesn't belong to the view results in + * undefined behavior. + * + * @tparam First Index of a component to get. + * @tparam Other Indexes of other components to get. + * @param entt A valid identifier. + * @return The components assigned to the entity. + */ + template + [[nodiscard]] decltype(auto) get(const entity_type entt) const { + if constexpr(sizeof...(Other) == 0) { + return storage().get(entt); + } else { + return std::tuple_cat(storage().get_as_tuple(entt), storage().get_as_tuple(entt)...); } } @@ -528,92 +482,46 @@ public: * void(Type &...); * @endcode * - * @note - * Empty types aren't explicitly instantiated and therefore they are never - * returned during iterations. - * * @tparam Func Type of the function object to invoke. * @param func A valid function object. */ template void each(Func func) const { - ((std::get *>(pools) == view ? traverse(std::move(func)) : void()), ...); + pick_and_each(func, std::index_sequence_for{}); } /** - * @brief Iterates entities and components and applies the given function - * object to them. + * @brief Returns an iterable object to use to _visit_ a view. * - * The pool of the suggested component is used to lead the iterations. The - * returned entities will therefore respect the order of the pool associated - * with that type. - * - * @sa each - * - * @tparam Comp Type of component to use to drive the iteration. - * @tparam Func Type of the function object to invoke. - * @param func A valid function object. - */ - template - void each(Func func) const { - use(); - traverse(std::move(func)); - } - - /** - * @brief Returns an iterable object to use to _visit_ the view. - * - * The iterable object returns tuples that contain the current entity and a - * set of references to its non-empty components. The _constness_ of the + * The iterable object returns a tuple that contains the current entity and + * a set of references to its non-empty components. The _constness_ of the * components is as requested. * - * @note - * Empty types aren't explicitly instantiated and therefore they are never - * returned during iterations. - * * @return An iterable object to use to _visit_ the view. */ - [[nodiscard]] iterable_view each() const ENTT_NOEXCEPT { - return iterable_view{*this}; - } - - /** - * @brief Returns an iterable object to use to _visit_ the view. - * - * The pool of the suggested component is used to lead the iterations. The - * returned elements will therefore respect the order of the pool associated - * with that type. - * - * @sa each - * - * @tparam Comp Type of component to use to drive the iteration. - * @return An iterable object to use to _visit_ the view. - */ - template - [[nodiscard]] iterable_view each() const ENTT_NOEXCEPT { - use(); - return iterable_view{*this}; + [[nodiscard]] iterable each() const noexcept { + return {internal::extended_view_iterator{begin(), pools}, internal::extended_view_iterator{end(), pools}}; } /** * @brief Combines two views in a _more specific_ one (friend function). - * @tparam Id A valid entity type (see entt_traits for more details). - * @tparam ELhs Filter list of the first view. - * @tparam CLhs Component list of the first view. - * @tparam ERhs Filter list of the second view. - * @tparam CRhs Component list of the second view. + * @tparam OGet Component list of the view to combine with. + * @tparam OExclude Filter list of the view to combine with. + * @param other The view to combine with. * @return A more specific view. */ - template - friend auto operator|(const basic_view, CLhs...> &, const basic_view, CRhs...> &); + template + [[nodiscard]] auto operator|(const basic_view, exclude_t> &other) const noexcept { + return std::make_from_tuple, exclude_t>>( + std::apply([](auto *...curr) { return std::forward_as_tuple(*curr...); }, std::tuple_cat(pools, other.pools, filter, other.filter))); + } private: - const std::tuple *...> pools; - const std::tuple *...> filter; - mutable const basic_common_type *view; + std::tuple pools; + std::tuple filter; + const base_type *view; }; - /** * @brief Single component view specialization. * @@ -625,167 +533,99 @@ private: * * Iterators aren't invalidated if: * - * * New instances of the given component are created and assigned to entities. - * * The entity currently pointed is modified (as an example, the given - * component is removed from the entity to which the iterator points). + * * New elements are added to the storage. + * * The entity currently pointed is modified (for example, components are added + * or removed from it). * * The entity currently pointed is destroyed. * * In all other cases, modifying the pool iterated by the view in any way * invalidates all the iterators and using them results in undefined behavior. * - * @note - * Views share a reference to the underlying data structure of the registry that - * generated them. Therefore any change to the entities and to the components - * made by means of the registry are immediately reflected by views. - * - * @warning - * Lifetime of a view must not overcome that of the registry that generated it. - * In any other case, attempting to use a view results in undefined behavior. - * - * @tparam Entity A valid entity type (see entt_traits for more details). - * @tparam Component Type of component iterated by the view. + * @tparam Get Type of storage iterated by the view. */ -template -class basic_view_impl, Component> { - using basic_common_type = basic_sparse_set; - using storage_type = constness_as_t>::storage_type, Component>; - - class iterable final { - template - struct iterable_iterator final { - using difference_type = std::ptrdiff_t; - using value_type = decltype(std::tuple_cat(std::tuple{}, std::declval().get({}))); - using pointer = void; - using reference = value_type; - using iterator_category = std::input_iterator_tag; - - template - iterable_iterator(It... from, Discard...) ENTT_NOEXCEPT - : it{from...} - {} - - iterable_iterator & operator++() ENTT_NOEXCEPT { - return (++std::get(it), ...), *this; - } - - iterable_iterator operator++(int) ENTT_NOEXCEPT { - iterable_iterator orig = *this; - return ++(*this), orig; - } - - [[nodiscard]] reference operator*() const ENTT_NOEXCEPT { - return { *std::get(it)... }; - } - - [[nodiscard]] bool operator==(const iterable_iterator &other) const ENTT_NOEXCEPT { - return std::get<0>(other.it) == std::get<0>(it); - } - - [[nodiscard]] bool operator!=(const iterable_iterator &other) const ENTT_NOEXCEPT { - return !(*this == other); - } - - private: - std::tuple it; - }; - - public: - using iterator = std::conditional_t< - std::is_void_v().get({}))>, - iterable_iterator, - iterable_iterator().begin())> - >; - using reverse_iterator = std::conditional_t< - std::is_void_v().get({}))>, - iterable_iterator, - iterable_iterator().rbegin())> - >; - - iterable(storage_type &ref) - : pool{&ref} - {} - - [[nodiscard]] iterator begin() const ENTT_NOEXCEPT { - return iterator{pool->basic_common_type::begin(), pool->begin()}; - } - - [[nodiscard]] iterator end() const ENTT_NOEXCEPT { - return iterator{pool->basic_common_type::end(), pool->end()}; - } - - [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT { - return reverse_iterator{pool->basic_common_type::rbegin(), pool->rbegin()}; - } - - [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT { - return reverse_iterator{pool->basic_common_type::rend(), pool->rend()}; - } - - private: - storage_type * const pool; - }; +template +class basic_view, exclude_t<>, std::void_t::in_place_delete>>> { + template + friend class basic_view; public: /*! @brief Underlying entity identifier. */ - using entity_type = Entity; + using entity_type = typename Get::entity_type; /*! @brief Unsigned integer type. */ using size_type = std::size_t; + /*! @brief Common type among all storage types. */ + using base_type = typename Get::base_type; /*! @brief Random access iterator type. */ - using iterator = typename basic_common_type::iterator; + using iterator = typename base_type::iterator; /*! @brief Reversed iterator type. */ - using reverse_iterator = typename basic_common_type::reverse_iterator; + using reverse_iterator = typename base_type::reverse_iterator; /*! @brief Iterable view type. */ - using iterable_view = iterable; + using iterable = decltype(std::declval().each()); /*! @brief Default constructor to use to create empty, invalid views. */ - basic_view_impl() ENTT_NOEXCEPT + basic_view() noexcept : pools{}, - filter{} - {} + filter{} {} /** * @brief Constructs a single-type view from a storage class. * @param ref The storage for the type to iterate. */ - basic_view_impl(storage_type &ref) ENTT_NOEXCEPT + basic_view(Get &ref) noexcept : pools{&ref}, - filter{} - {} + filter{} {} + + /** + * @brief Constructs a single-type view from a storage class. + * @param ref The storage for the type to iterate. + */ + basic_view(std::tuple ref, std::tuple<> = {}) noexcept + : pools{&std::get<0>(ref)}, + filter{} {} + + /** + * @brief Returns the leading storage of a view. + * @return The leading storage of the view. + */ + [[nodiscard]] const base_type &handle() const noexcept { + return storage(); + } + + /** + * @brief Returns the storage for a given component type. + * @tparam Type Type of component of which to return the storage. + * @return The storage for the given component type. + */ + template + [[nodiscard]] decltype(auto) storage() const noexcept { + static_assert(std::is_same_v, typename Get::value_type>, "Invalid component type"); + return storage<0>(); + } + + /** + * @brief Returns the storage for a given index. + * @tparam Index Index of the storage to return. + * @return The storage for the given index. + */ + template + [[nodiscard]] decltype(auto) storage() const noexcept { + return *std::get(pools); + } /** * @brief Returns the number of entities that have the given component. * @return Number of entities that have the given component. */ - [[nodiscard]] size_type size() const ENTT_NOEXCEPT { - return std::get<0>(pools)->size(); + [[nodiscard]] size_type size() const noexcept { + return handle().size(); } /** * @brief Checks whether a view is empty. * @return True if the view is empty, false otherwise. */ - [[nodiscard]] bool empty() const ENTT_NOEXCEPT { - return std::get<0>(pools)->empty(); - } - - /** - * @brief Direct access to the raw representation offered by the storage. - * @return A pointer to the array of components. - */ - [[nodiscard]] auto raw() const ENTT_NOEXCEPT { - return std::get<0>(pools)->raw(); - } - - /** - * @brief Direct access to the list of entities. - * - * The returned pointer is such that range `[data(), data() + size())` is - * always a valid range, even if the container is empty. - * - * @return A pointer to the array of entities. - */ - [[nodiscard]] auto data() const ENTT_NOEXCEPT { - return std::get<0>(pools)->data(); + [[nodiscard]] bool empty() const noexcept { + return handle().empty(); } /** @@ -796,8 +636,8 @@ public: * * @return An iterator to the first entity of the view. */ - [[nodiscard]] iterator begin() const ENTT_NOEXCEPT { - return std::get<0>(pools)->basic_common_type::begin(); + [[nodiscard]] iterator begin() const noexcept { + return handle().begin(); } /** @@ -809,8 +649,8 @@ public: * * @return An iterator to the entity following the last entity of the view. */ - [[nodiscard]] iterator end() const ENTT_NOEXCEPT { - return std::get<0>(pools)->basic_common_type::end(); + [[nodiscard]] iterator end() const noexcept { + return handle().end(); } /** @@ -821,8 +661,8 @@ public: * * @return An iterator to the first entity of the reversed view. */ - [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT { - return std::get<0>(pools)->basic_common_type::rbegin(); + [[nodiscard]] reverse_iterator rbegin() const noexcept { + return handle().rbegin(); } /** @@ -836,8 +676,8 @@ public: * @return An iterator to the entity following the last entity of the * reversed view. */ - [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT { - return std::get<0>(pools)->basic_common_type::rend(); + [[nodiscard]] reverse_iterator rend() const noexcept { + return handle().rend(); } /** @@ -845,9 +685,8 @@ public: * @return The first entity of the view if one exists, the null entity * otherwise. */ - [[nodiscard]] entity_type front() const { - const auto it = begin(); - return it != end() ? *it : null; + [[nodiscard]] entity_type front() const noexcept { + return empty() ? null : *begin(); } /** @@ -855,20 +694,18 @@ public: * @return The last entity of the view if one exists, the null entity * otherwise. */ - [[nodiscard]] entity_type back() const { - const auto it = rbegin(); - return it != rend() ? *it : null; + [[nodiscard]] entity_type back() const noexcept { + return empty() ? null : *rbegin(); } /** * @brief Finds an entity. - * @param entt A valid entity identifier. + * @param entt A valid identifier. * @return An iterator to the given entity if it's found, past the end * iterator otherwise. */ - [[nodiscard]] iterator find(const entity_type entt) const { - const auto it = std::get<0>(pools)->find(entt); - return it != end() && *it == entt ? it : end(); + [[nodiscard]] iterator find(const entity_type entt) const noexcept { + return contains(entt) ? handle().find(entt) : end(); } /** @@ -880,50 +717,59 @@ public: return begin()[pos]; } + /** + * @brief Returns the component assigned to the given entity. + * @param entt A valid identifier. + * @return The component assigned to the given entity. + */ + [[nodiscard]] decltype(auto) operator[](const entity_type entt) const { + return storage().get(entt); + } + /** * @brief Checks if a view is properly initialized. * @return True if the view is properly initialized, false otherwise. */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { + [[nodiscard]] explicit operator bool() const noexcept { return std::get<0>(pools) != nullptr; } /** * @brief Checks if a view contains an entity. - * @param entt A valid entity identifier. + * @param entt A valid identifier. * @return True if the view contains the given entity, false otherwise. */ - [[nodiscard]] bool contains(const entity_type entt) const { - return std::get<0>(pools)->contains(entt); + [[nodiscard]] bool contains(const entity_type entt) const noexcept { + return handle().contains(entt); } /** * @brief Returns the component assigned to the given entity. * - * Prefer this function instead of `registry::get` during iterations. It has - * far better performance than its counterpart. - * * @warning - * Attempting to use an invalid component type results in a compilation - * error. Attempting to use an entity that doesn't belong to the view - * results in undefined behavior. + * Attempting to use an entity that doesn't belong to the view results in + * undefined behavior. * - * @tparam Comp Types of components to get. - * @param entt A valid entity identifier. + * @tparam Type Type or index of the component to get. + * @param entt A valid identifier. * @return The component assigned to the entity. */ - template + template [[nodiscard]] decltype(auto) get(const entity_type entt) const { - ENTT_ASSERT(contains(entt), "View does not contain entity"); - - if constexpr(sizeof...(Comp) == 0) { - return get_as_tuple(*std::get<0>(pools), entt); + if constexpr(sizeof...(Type) == 0) { + return storage().get_as_tuple(entt); } else { - static_assert(std::is_same_v, "Invalid component type"); - return std::get<0>(pools)->get(entt); + static_assert((std::is_same_v, typename Get::value_type> && ...), "Invalid component type"); + return storage().get(entt); } } + /*! @copydoc get */ + template + [[nodiscard]] decltype(auto) get(const entity_type entt) const { + return storage().get(entt); + } + /** * @brief Iterates entities and components and applies the given function * object to them. @@ -935,8 +781,8 @@ public: * forms: * * @code{.cpp} - * void(const entity_type, Component &); - * void(Component &); + * void(const entity_type, Type &); + * void(typename Type &); * @endcode * * @note @@ -948,109 +794,68 @@ public: */ template void each(Func func) const { - if constexpr(std::is_void_v(pools)->get({}))>) { - if constexpr(std::is_invocable_v) { - for(auto pos = size(); pos; --pos) { - func(); - } - } else { - for(auto entity: *this) { - func(entity); - } + if constexpr(is_applicable_v) { + for(const auto pack: each()) { + std::apply(func, pack); + } + } else if constexpr(ignore_as_empty_v) { + for(size_type pos{}, last = size(); pos < last; ++pos) { + func(); } } else { - if constexpr(is_applicable_v) { - for(const auto pack: each()) { - std::apply(func, pack); - } - } else { - for(auto &&component: *std::get<0>(pools)) { - func(component); - } + for(auto &&component: storage()) { + func(component); } } } /** - * @brief Returns an iterable object to use to _visit_ the view. + * @brief Returns an iterable object to use to _visit_ a view. * - * The iterable object returns tuples that contain the current entity and a - * reference to its component if it's a non-empty one. The _constness_ of + * The iterable object returns a tuple that contains the current entity and + * a reference to its component if it's a non-empty one. The _constness_ of * the component is as requested. * - * @note - * Empty types aren't explicitly instantiated and therefore they are never - * returned during iterations. - * * @return An iterable object to use to _visit_ the view. */ - [[nodiscard]] iterable_view each() const ENTT_NOEXCEPT { - return iterable_view{*std::get<0>(pools)}; + [[nodiscard]] iterable each() const noexcept { + return storage().each(); } /** * @brief Combines two views in a _more specific_ one (friend function). - * @tparam Id A valid entity type (see entt_traits for more details). - * @tparam ELhs Filter list of the first view. - * @tparam CLhs Component list of the first view. - * @tparam ERhs Filter list of the second view. - * @tparam CRhs Component list of the second view. + * @tparam OGet Component list of the view to combine with. + * @tparam OExclude Filter list of the view to combine with. + * @param other The view to combine with. * @return A more specific view. */ - template - friend auto operator|(const basic_view, CLhs...> &, const basic_view, CRhs...> &); + template + [[nodiscard]] auto operator|(const basic_view, exclude_t> &other) const noexcept { + return std::make_from_tuple, exclude_t>>( + std::apply([](auto *...curr) { return std::forward_as_tuple(*curr...); }, std::tuple_cat(pools, other.pools, other.filter))); + } private: - const std::tuple pools; - const std::tuple<> filter; + std::tuple pools; + std::tuple<> filter; }; - -/** - * @brief View implementation dispatcher. - * @tparam Entity A valid entity type (see entt_traits for more details). - * @tparam Exclude Types of components used to filter the view. - * @tparam Component Types of components iterated by the view. - */ -template -struct basic_view, Component...> - : basic_view_impl>::in_place_delete...>, stable_storage_policy, packed_storage_policy>, Entity, exclude_t, Component...> -{ - /*! @brief Most restrictive storage policy of all component types. */ - using storage_policy = std::conditional_t>::in_place_delete...>, stable_storage_policy, packed_storage_policy>; - using basic_view_impl, Component...>::basic_view_impl; -}; - - /** * @brief Deduction guide. - * @tparam Storage Type of storage classes used to create the view. + * @tparam Type Type of storage classes used to create the view. * @param storage The storage for the types to iterate. */ -template -basic_view(Storage &... storage) --> basic_view, entt::exclude_t<>, constness_as_t...>; - +template +basic_view(Type &...storage) -> basic_view, exclude_t<>>; /** - * @brief Combines two views in a _more specific_ one. - * @tparam Entity A valid entity type (see entt_traits for more details). - * @tparam ELhs Filter list of the first view. - * @tparam CLhs Component list of the first view. - * @tparam ERhs Filter list of the second view. - * @tparam CRhs Component list of the second view. - * @param lhs A valid reference to the first view. - * @param rhs A valid reference to the second view. - * @return A more specific view. + * @brief Deduction guide. + * @tparam Get Types of components iterated by the view. + * @tparam Exclude Types of components used to filter the view. */ -template -[[nodiscard]] auto operator|(const basic_view, CLhs...> &lhs, const basic_view, CRhs...> &rhs) { - using view_type = basic_view, CLhs..., CRhs...>; - return std::apply([](auto *... storage) { return view_type{*storage...}; }, std::tuple_cat(lhs.pools, rhs.pools, lhs.filter, rhs.filter)); -} - - -} +template +basic_view(std::tuple, std::tuple = {}) -> basic_view, exclude_t>; +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/entt.hpp b/LiteLoader/third-party/include/entt/entt.hpp index 1482bbc..3544fb6 100644 --- a/LiteLoader/third-party/include/entt/entt.hpp +++ b/LiteLoader/third-party/include/entt/entt.hpp @@ -1,51 +1,64 @@ -#include "third-party/include/entt/config/version.h" -#include "third-party/include/entt/core/algorithm.hpp" -#include "third-party/include/entt/core/any.hpp" -#include "third-party/include/entt/core/attribute.h" -#include "third-party/include/entt/core/family.hpp" -#include "third-party/include/entt/core/hashed_string.hpp" -#include "third-party/include/entt/core/ident.hpp" -#include "third-party/include/entt/core/monostate.hpp" -#include "third-party/include/entt/core/type_info.hpp" -#include "third-party/include/entt/core/type_traits.hpp" -#include "third-party/include/entt/core/utility.hpp" -#include "third-party/include/entt/entity/component.hpp" -#include "third-party/include/entt/entity/entity.hpp" -#include "third-party/include/entt/entity/group.hpp" -#include "third-party/include/entt/entity/handle.hpp" -#include "third-party/include/entt/entity/helper.hpp" -#include "third-party/include/entt/entity/observer.hpp" -#include "third-party/include/entt/entity/organizer.hpp" -#include "third-party/include/entt/entity/poly_storage.hpp" -#include "third-party/include/entt/entity/registry.hpp" -#include "third-party/include/entt/entity/runtime_view.hpp" -#include "third-party/include/entt/entity/snapshot.hpp" -#include "third-party/include/entt/entity/sparse_set.hpp" -#include "third-party/include/entt/entity/storage.hpp" -#include "third-party/include/entt/entity/utility.hpp" -#include "third-party/include/entt/entity/view.hpp" -#include "third-party/include/entt/locator/locator.hpp" -#include "third-party/include/entt/meta/adl_pointer.hpp" -#include "third-party/include/entt/meta/container.hpp" -#include "third-party/include/entt/meta/ctx.hpp" -#include "third-party/include/entt/meta/factory.hpp" -#include "third-party/include/entt/meta/meta.hpp" -#include "third-party/include/entt/meta/node.hpp" -#include "third-party/include/entt/meta/pointer.hpp" -#include "third-party/include/entt/meta/policy.hpp" -#include "third-party/include/entt/meta/range.hpp" -#include "third-party/include/entt/meta/resolve.hpp" -#include "third-party/include/entt/meta/template.hpp" -#include "third-party/include/entt/meta/type_traits.hpp" -#include "third-party/include/entt/meta/utility.hpp" -#include "third-party/include/entt/platform/android-ndk-r17.hpp" -#include "third-party/include/entt/poly/poly.hpp" -#include "third-party/include/entt/process/process.hpp" -#include "third-party/include/entt/process/scheduler.hpp" -#include "third-party/include/entt/resource/cache.hpp" -#include "third-party/include/entt/resource/handle.hpp" -#include "third-party/include/entt/resource/loader.hpp" -#include "third-party/include/entt/signal/delegate.hpp" -#include "third-party/include/entt/signal/dispatcher.hpp" -#include "third-party/include/entt/signal/emitter.hpp" -#include "third-party/include/entt/signal/sigh.hpp" +// IWYU pragma: begin_exports +#include "config/config.h" +#include "config/macro.h" +#include "config/version.h" +#include "container/dense_map.hpp" +#include "container/dense_set.hpp" +#include "core/algorithm.hpp" +#include "core/any.hpp" +#include "core/attribute.h" +#include "core/compressed_pair.hpp" +#include "core/enum.hpp" +#include "core/family.hpp" +#include "core/hashed_string.hpp" +#include "core/ident.hpp" +#include "core/iterator.hpp" +#include "core/memory.hpp" +#include "core/monostate.hpp" +#include "core/tuple.hpp" +#include "core/type_info.hpp" +#include "core/type_traits.hpp" +#include "core/utility.hpp" +#include "entity/component.hpp" +#include "entity/entity.hpp" +#include "entity/group.hpp" +#include "entity/handle.hpp" +#include "entity/helper.hpp" +#include "entity/observer.hpp" +#include "entity/organizer.hpp" +#include "entity/registry.hpp" +#include "entity/runtime_view.hpp" +#include "entity/snapshot.hpp" +#include "entity/sparse_set.hpp" +#include "entity/storage.hpp" +#include "entity/storage_mixin.hpp" +#include "entity/view.hpp" +#include "graph/adjacency_matrix.hpp" +#include "graph/dot.hpp" +#include "graph/flow.hpp" +#include "locator/locator.hpp" +#include "meta/adl_pointer.hpp" +#include "meta/container.hpp" +#include "meta/context.hpp" +#include "meta/factory.hpp" +#include "meta/meta.hpp" +#include "meta/node.hpp" +#include "meta/pointer.hpp" +#include "meta/policy.hpp" +#include "meta/range.hpp" +#include "meta/resolve.hpp" +#include "meta/template.hpp" +#include "meta/type_traits.hpp" +#include "meta/utility.hpp" +#include "platform/android-ndk-r17.hpp" +#include "poly/poly.hpp" +#include "process/process.hpp" +#include "process/scheduler.hpp" +#include "resource/cache.hpp" +#include "resource/loader.hpp" +#include "resource/resource.hpp" +#include "signal/delegate.hpp" +#include "signal/dispatcher.hpp" +#include "signal/emitter.hpp" +#include "signal/sigh.hpp" +// IWYU pragma: end_exports diff --git a/LiteLoader/third-party/include/entt/fwd.hpp b/LiteLoader/third-party/include/entt/fwd.hpp index 8fadcc5..4b6e60c 100644 --- a/LiteLoader/third-party/include/entt/fwd.hpp +++ b/LiteLoader/third-party/include/entt/fwd.hpp @@ -1,5 +1,11 @@ -#include "third-party/include/entt/core/fwd.hpp" -#include "third-party/include/entt/entity/fwd.hpp" -#include "third-party/include/entt/poly/fwd.hpp" -#include "third-party/include/entt/resource/fwd.hpp" -#include "third-party/include/entt/signal/fwd.hpp" +// IWYU pragma: begin_exports +#include "container/fwd.hpp" +#include "core/fwd.hpp" +#include "entity/fwd.hpp" +#include "graph/fwd.hpp" +#include "meta/fwd.hpp" +#include "poly/fwd.hpp" +#include "process/fwd.hpp" +#include "resource/fwd.hpp" +#include "signal/fwd.hpp" +// IWYU pragma: end_exports diff --git a/LiteLoader/third-party/include/entt/locator/locator.hpp b/LiteLoader/third-party/include/entt/locator/locator.hpp index e059383..e33377a 100644 --- a/LiteLoader/third-party/include/entt/locator/locator.hpp +++ b/LiteLoader/third-party/include/entt/locator/locator.hpp @@ -1,111 +1,135 @@ #ifndef ENTT_LOCATOR_LOCATOR_HPP #define ENTT_LOCATOR_LOCATOR_HPP - #include #include -#include "third-party/include/entt/config/config.h" - +#include "../config/config.h" namespace entt { - /** * @brief Service locator, nothing more. * - * A service locator can be used to do what it promises: locate services.
+ * A service locator is used to do what it promises: locate services.
* Usually service locators are tightly bound to the services they expose and - * thus it's hard to define a general purpose class to do that. This template - * based implementation tries to fill the gap and to get rid of the burden of - * defining a different specific locator for each application. + * thus it's hard to define a general purpose class to do that. This tiny class + * tries to fill the gap and to get rid of the burden of defining a different + * specific locator for each application. * - * @tparam Service Type of service managed by the locator. + * @note + * Users shouldn't retain references to a service. The recommended way is to + * retrieve the service implementation currently set each and every time the + * need for it arises. The risk is to incur in unexpected behaviors otherwise. + * + * @tparam Service Service type. */ template -struct service_locator { - /*! @brief Type of service offered. */ - using service_type = Service; +class locator final { + class service_handle { + friend class locator; + std::shared_ptr value{}; + }; + +public: + /*! @brief Service type. */ + using type = Service; + /*! @brief Service node type. */ + using node_type = service_handle; /*! @brief Default constructor, deleted on purpose. */ - service_locator() = delete; + locator() = delete; /*! @brief Default destructor, deleted on purpose. */ - ~service_locator() = delete; + ~locator() = delete; /** - * @brief Tests if a valid service implementation is set. - * @return True if the service is set, false otherwise. + * @brief Checks whether a service locator contains a value. + * @return True if the service locator contains a value, false otherwise. */ - [[nodiscard]] static bool empty() ENTT_NOEXCEPT { - return !static_cast(service); + [[nodiscard]] static bool has_value() noexcept { + return (service != nullptr); } /** - * @brief Returns a weak pointer to a service implementation, if any. - * - * Clients of a service shouldn't retain references to it. The recommended - * way is to retrieve the service implementation currently set each and - * every time the need of using it arises. Otherwise users can incur in - * unexpected behaviors. - * - * @return A reference to the service implementation currently set, if any. - */ - [[nodiscard]] static std::weak_ptr get() ENTT_NOEXCEPT { - return service; - } - - /** - * @brief Returns a weak reference to a service implementation, if any. - * - * Clients of a service shouldn't retain references to it. The recommended - * way is to retrieve the service implementation currently set each and - * every time the need of using it arises. Otherwise users can incur in - * unexpected behaviors. + * @brief Returns a reference to a valid service, if any. * * @warning - * In case no service implementation has been set, a call to this function - * results in undefined behavior. + * Invoking this function can result in undefined behavior if the service + * hasn't been set yet. * - * @return A reference to the service implementation currently set, if any. + * @return A reference to the service currently set, if any. */ - [[nodiscard]] static Service & ref() ENTT_NOEXCEPT { + [[nodiscard]] static Service &value() noexcept { + ENTT_ASSERT(has_value(), "Service not available"); return *service; } /** - * @brief Sets or replaces a service. - * @tparam Impl Type of the new service to use. - * @tparam Args Types of arguments to use to construct the service. - * @param args Parameters to use to construct the service. + * @brief Returns a service if available or sets it from a fallback type. + * + * Arguments are used only if a service doesn't already exist. In all other + * cases, they are discarded. + * + * @tparam Args Types of arguments to use to construct the fallback service. + * @tparam Impl Fallback service type. + * @param args Parameters to use to construct the fallback service. + * @return A reference to a valid service. */ template - static void set(Args &&... args) { - service = std::make_shared(std::forward(args)...); + [[nodiscard]] static Service &value_or(Args &&...args) { + return service ? *service : emplace(std::forward(args)...); } /** * @brief Sets or replaces a service. - * @param ptr Service to use to replace the current one. + * @tparam Impl Service type. + * @tparam Args Types of arguments to use to construct the service. + * @param args Parameters to use to construct the service. + * @return A reference to a valid service. */ - static void set(std::shared_ptr ptr) { - ENTT_ASSERT(static_cast(ptr), "Null service not allowed"); - service = std::move(ptr); + template + static Service &emplace(Args &&...args) { + service = std::make_shared(std::forward(args)...); + return *service; } /** - * @brief Resets a service. - * - * The service is no longer valid after a reset. + * @brief Sets or replaces a service using a given allocator. + * @tparam Impl Service type. + * @tparam Allocator Type of allocator used to manage memory and elements. + * @tparam Args Types of arguments to use to construct the service. + * @param alloc The allocator to use. + * @param args Parameters to use to construct the service. + * @return A reference to a valid service. */ - static void reset() { - service.reset(); + template + static Service &allocate_emplace(Allocator alloc, Args &&...args) { + service = std::allocate_shared(alloc, std::forward(args)...); + return *service; + } + + /** + * @brief Returns a handle to the underlying service. + * @return A handle to the underlying service. + */ + static node_type handle() noexcept { + node_type node{}; + node.value = service; + return node; + } + + /** + * @brief Resets or replaces a service. + * @param other Optional handle with which to replace the service. + */ + static void reset(const node_type &other = {}) noexcept { + service = other.value; } private: - inline static std::shared_ptr service = nullptr; + // std::shared_ptr because of its type erased allocator which is useful here + inline static std::shared_ptr service{}; }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/meta/adl_pointer.hpp b/LiteLoader/third-party/include/entt/meta/adl_pointer.hpp index 39e747b..5bb768a 100644 --- a/LiteLoader/third-party/include/entt/meta/adl_pointer.hpp +++ b/LiteLoader/third-party/include/entt/meta/adl_pointer.hpp @@ -1,10 +1,8 @@ #ifndef ENTT_META_ADL_POINTER_HPP #define ENTT_META_ADL_POINTER_HPP - namespace entt { - /** * @brief ADL based lookup function for dereferencing meta pointer-like types. * @tparam Type Element type. @@ -16,7 +14,6 @@ decltype(auto) dereference_meta_pointer_like(const Type &value) { return *value; } - /** * @brief Fake ADL based lookup function for meta pointer-like types. * @tparam Type Element type. @@ -33,8 +30,6 @@ struct adl_meta_pointer_like { } }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/meta/container.hpp b/LiteLoader/third-party/include/entt/meta/container.hpp index 5283b87..dc8a173 100644 --- a/LiteLoader/third-party/include/entt/meta/container.hpp +++ b/LiteLoader/third-party/include/entt/meta/container.hpp @@ -1,406 +1,247 @@ #ifndef ENTT_META_CONTAINER_HPP #define ENTT_META_CONTAINER_HPP - #include +#include +#include +#include #include #include #include #include #include -#include #include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/type_traits.hpp" +#include "../container/dense_map.hpp" +#include "../container/dense_set.hpp" +#include "context.hpp" +#include "meta.hpp" #include "type_traits.hpp" - namespace entt { - /** - * @brief Container traits. - * @tparam Container Type of the underlying container. - * @tparam Trait Traits associated with the underlying container. + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. */ -template class... Trait> -struct meta_container_traits: public Trait... { - /*! @brief Type of container. */ - using type = Container; -}; +namespace internal { -/** - * @brief Basic STL-compatible container traits - * @tparam Container The type of the container. - */ -template -struct basic_container { - /** - * @brief Returns the size of the given container. - * @param cont The container for which to return the size. - * @return The size of the given container. - */ - [[nodiscard]] static typename Container::size_type size(const Container &cont) ENTT_NOEXCEPT { - return cont.size(); +template +struct is_dynamic_sequence_container: std::false_type {}; + +template +struct is_dynamic_sequence_container>: std::true_type {}; + +template +struct is_key_only_meta_associative_container: std::true_type {}; + +template +struct is_key_only_meta_associative_container>: std::false_type {}; + +template +struct basic_meta_sequence_container_traits { + using iterator = meta_sequence_container::iterator; + using size_type = std::size_t; + + [[nodiscard]] static size_type size(const any &container) noexcept { + return any_cast(container).size(); } - /** - * @brief Returns an iterator to the first element of the given container. - * @param cont The container for which to return the iterator. - * @return An iterator to the first element of the given container. - */ - [[nodiscard]] static typename Container::iterator begin(Container &cont) { - return cont.begin(); - } + [[nodiscard]] static bool resize([[maybe_unused]] any &container, [[maybe_unused]] size_type sz) { + if constexpr(is_dynamic_sequence_container::value) { + if(auto *const cont = any_cast(&container); cont) { + cont->resize(sz); + return true; + } + } - /** - * @brief Returns an iterator to the first element of the given container. - * @param cont The container for which to return the iterator. - * @return An iterator to the first element of the given container. - */ - [[nodiscard]] static typename Container::const_iterator cbegin(const Container &cont) { - return cont.begin(); - } - - /** - * @brief Returns an iterator past the last element of the given container. - * @param cont The container for which to return the iterator. - * @return An iterator past the last element of the given container. - */ - [[nodiscard]] static typename Container::iterator end(Container &cont) { - return cont.end(); - } - - /** - * @brief Returns an iterator past the last element of the given container. - * @param cont The container for which to return the iterator. - * @return An iterator past the last element of the given container. - */ - [[nodiscard]] static typename Container::const_iterator cend(const Container &cont) { - return cont.end(); - } -}; - - -/** - * @brief Basic STL-compatible associative container traits - * @tparam Container The type of the container. - */ -template -struct basic_associative_container { - /** - * @brief Returns an iterator to the element with key equivalent to the - * given one, if any. - * @param cont The container in which to search for the element. - * @param key The key of the element to search. - * @return An iterator to the element with the given key, if any. - */ - [[nodiscard]] static typename Container::iterator find(Container &cont, const typename Container::key_type &key) { - return cont.find(key); - } - - /*! @copydoc find */ - [[nodiscard]] static typename Container::const_iterator cfind(const Container &cont, const typename Container::key_type &key) { - return cont.find(key); - } -}; - - -/** - * @brief Basic STL-compatible dynamic container traits - * @tparam Container The type of the container. - */ -template -struct basic_dynamic_container { - /** - * @brief Clears the content of the given container. - * @param cont The container for which to clear the content. - * @return True in case of success, false otherwise. - */ - [[nodiscard]] static bool clear([[maybe_unused]] Container &cont) { - return cont.clear(), true; - } -}; - - -/** - * @brief Basic STL-compatible dynamic associative container traits - * @tparam Container The type of the container. - */ -template -struct basic_dynamic_associative_container { - /** - * @brief Removes the specified element from the given container. - * @param cont The container from which to remove the element. - * @param key The element to remove. - * @return A bool denoting whether the removal took place. - */ - [[nodiscard]] static bool erase([[maybe_unused]] Container &cont, [[maybe_unused]] const typename Container::key_type &key) { - const auto sz = cont.size(); - return cont.erase(key) != sz; - } -}; - - -/** - * @brief Basic STL-compatible sequence container traits - * @tparam Container The type of the container. - */ -template -struct basic_sequence_container { - /** - * @brief Returns a reference to the element at the specified location of - * the given container (no bounds checking is performed). - * @param cont The container from which to get the element. - * @param pos The position of the element to return. - * @return A reference to the requested element. - */ - [[nodiscard]] static typename Container::reference get(Container &cont, typename Container::size_type pos) { - return cont[pos]; - } - - /*! @copydoc get */ - [[nodiscard]] static typename Container::const_reference cget(const Container &cont, typename Container::size_type pos) { - return cont[pos]; - } -}; - - -/** - * @brief STL-compatible dynamic associative key-only container traits - * @tparam Container The type of the container. - */ -template -struct dynamic_associative_key_only_container { - /** - * @brief Inserts an element into the given container. - * @param cont The container in which to insert the element. - * @param key The element to insert. - * @return A bool denoting whether the insertion took place. - */ - [[nodiscard]] static bool insert([[maybe_unused]] Container &cont, [[maybe_unused]] const typename Container::key_type &key) { - return cont.insert(key).second; - } -}; - - -/** - * @brief STL-compatible dynamic key-value associative container traits - * @tparam Container The type of the container. - */ -template -struct dynamic_associative_key_value_container { - /** - * @brief Inserts an element (a key/value pair) into the given container. - * @param cont The container in which to insert the element. - * @param key The key of the element to insert. - * @param value The value of the element to insert. - * @return A bool denoting whether the insertion took place. - */ - [[nodiscard]] static bool insert([[maybe_unused]] Container &cont, [[maybe_unused]] const typename Container::key_type &key, [[maybe_unused]] const typename Container::mapped_type &value) { - return cont.insert(std::make_pair(key, value)).second; - } -}; - - -/** - * @brief STL-compatible dynamic sequence container traits - * @tparam Container The type of the container. - */ -template -struct dynamic_sequence_container { - /** - * @brief Resizes the given container to contain the given number of - * elements. - * @param cont The container to resize. - * @param sz The new size of the container. - * @return True in case of success, false otherwise. - */ - [[nodiscard]] static bool resize([[maybe_unused]] Container &cont, [[maybe_unused]] typename Container::size_type sz) { - return cont.resize(sz), true; - } - - /** - * @brief Inserts an element at the specified location of the given - * container. - * @param cont The container into which to insert the element. - * @param it Iterator before which the element will be inserted. - * @param value Element value to insert. - * @return A pair consisting of an iterator to the inserted element (in case - * of success) and a bool denoting whether the insertion took place. - */ - [[nodiscard]] static std::pair insert([[maybe_unused]] Container &cont, [[maybe_unused]] typename Container::const_iterator it, [[maybe_unused]] const typename Container::value_type &value) { - return { cont.insert(it, value), true }; - } - - /** - * @brief Removes the element at the specified location from the given - * container. - * @param cont The container from which to remove the element. - * @param it Iterator to the element to remove. - * @return A pair consisting of an iterator following the last removed - * element (in case of success) and a bool denoting whether the insertion - * took place. - */ - [[nodiscard]] static std::pair erase([[maybe_unused]] Container &cont, [[maybe_unused]] typename Container::const_iterator it) { - return { cont.erase(it), true }; - } -}; - - -/** - * @brief STL-compatible fixed sequence container traits - * @tparam Container The type of the container. - */ -template -struct fixed_sequence_container { - /** - * @brief Does nothing. - * @return False to indicate failure in all cases. - */ - [[nodiscard]] static bool resize(const Container &, typename Container::size_type) { return false; } - /** - * @brief Does nothing. - * @return False to indicate failure in all cases. - */ - [[nodiscard]] static bool clear(const Container &) { - return false; + [[nodiscard]] static iterator iter(const meta_ctx &ctx, any &container, const bool as_end) { + if(auto *const cont = any_cast(&container); cont) { + return iterator{ctx, as_end ? cont->end() : cont->begin()}; + } + + const Type &as_const = any_cast(container); + return iterator{ctx, as_end ? as_const.end() : as_const.begin()}; } - /** - * @brief Does nothing. - * @return A pair consisting of an invalid iterator and a false value to - * indicate failure in all cases. - */ - [[nodiscard]] static std::pair insert(const Container &, typename Container::const_iterator, const typename Container::value_type &) { - return { {}, false }; - } + [[nodiscard]] static iterator insert_or_erase([[maybe_unused]] const meta_ctx &ctx, [[maybe_unused]] any &container, [[maybe_unused]] const any &handle, [[maybe_unused]] meta_any &value) { + if constexpr(is_dynamic_sequence_container::value) { + if(auto *const cont = any_cast(&container); cont) { + typename Type::const_iterator it{}; - /** - * @brief Does nothing. - * @return A pair consisting of an invalid iterator and a false value to - * indicate failure in all cases. - */ - [[nodiscard]] static std::pair erase(const Container &, typename Container::const_iterator) { - return { {}, false }; + if(auto *non_const = any_cast(&handle); non_const) { + it = *non_const; + } else { + it = any_cast(handle); + } + + if(value) { + // this abomination is necessary because only on macos value_type and const_reference are different types for std::vector + if(value.allow_cast() || value.allow_cast()) { + const auto *element = value.try_cast>(); + return iterator{ctx, cont->insert(it, element ? *element : value.cast())}; + } + } else { + return iterator{ctx, cont->erase(it)}; + } + } + } + + return iterator{}; } }; +template +struct basic_meta_associative_container_traits { + using iterator = meta_associative_container::iterator; + using size_type = std::size_t; + + static constexpr auto key_only = is_key_only_meta_associative_container::value; + + [[nodiscard]] static size_type size(const any &container) noexcept { + return any_cast(container).size(); + } + + [[nodiscard]] static bool clear(any &container) { + if(auto *const cont = any_cast(&container); cont) { + cont->clear(); + return true; + } + + return false; + } + + [[nodiscard]] static iterator iter(const meta_ctx &ctx, any &container, const bool as_end) { + if(auto *const cont = any_cast(&container); cont) { + return iterator{ctx, std::bool_constant{}, as_end ? cont->end() : cont->begin()}; + } + + const auto &as_const = any_cast(container); + return iterator{ctx, std::bool_constant{}, as_end ? as_const.end() : as_const.begin()}; + } + + [[nodiscard]] static size_type insert_or_erase(any &container, meta_any &key, meta_any &value) { + if(auto *const cont = any_cast(&container); cont && key.allow_cast()) { + if(value) { + if constexpr(key_only) { + return cont->insert(key.cast()).second; + } else { + return value.allow_cast() && cont->emplace(key.cast(), value.cast()).second; + } + } else { + return cont->erase(key.cast()); + } + } + + return 0u; + } + + [[nodiscard]] static iterator find(const meta_ctx &ctx, any &container, meta_any &key) { + if(key.allow_cast()) { + if(auto *const cont = any_cast(&container); cont) { + return iterator{ctx, std::bool_constant{}, cont->find(key.cast())}; + } + + return iterator{ctx, std::bool_constant{}, any_cast(container).find(key.cast())}; + } + + return iterator{}; + } +}; + +} // namespace internal + +/** + * Internal details not to be documented. + * @endcond + */ /** * @brief Meta sequence container traits for `std::vector`s of any type. - * @tparam Type The type of elements. - * @tparam Args Other arguments. + * @tparam Args Template arguments for the container. */ -template -struct meta_sequence_container_traits> - : meta_container_traits< - std::vector, - basic_container, - basic_dynamic_container, - basic_sequence_container, - dynamic_sequence_container - > -{}; - +template +struct meta_sequence_container_traits> + : internal::basic_meta_sequence_container_traits> {}; /** * @brief Meta sequence container traits for `std::array`s of any type. - * @tparam Type The type of elements. - * @tparam N The number of elements. + * @tparam Type Template arguments for the container. + * @tparam N Template arguments for the container. */ template struct meta_sequence_container_traits> - : meta_container_traits< - std::array, - basic_container, - basic_sequence_container, - fixed_sequence_container - > -{}; + : internal::basic_meta_sequence_container_traits> {}; +/** + * @brief Meta sequence container traits for `std::list`s of any type. + * @tparam Args Template arguments for the container. + */ +template +struct meta_sequence_container_traits> + : internal::basic_meta_sequence_container_traits> {}; + +/** + * @brief Meta sequence container traits for `std::deque`s of any type. + * @tparam Args Template arguments for the container. + */ +template +struct meta_sequence_container_traits> + : internal::basic_meta_sequence_container_traits> {}; /** * @brief Meta associative container traits for `std::map`s of any type. - * @tparam Key The key type of elements. - * @tparam Value The value type of elements. - * @tparam Args Other arguments. + * @tparam Args Template arguments for the container. */ -template -struct meta_associative_container_traits> - : meta_container_traits< - std::map, - basic_container, - basic_associative_container, - basic_dynamic_container, - basic_dynamic_associative_container, - dynamic_associative_key_value_container - > -{}; - +template +struct meta_associative_container_traits> + : internal::basic_meta_associative_container_traits> {}; /** * @brief Meta associative container traits for `std::unordered_map`s of any * type. - * @tparam Key The key type of elements. - * @tparam Value The value type of elements. - * @tparam Args Other arguments. + * @tparam Args Template arguments for the container. */ -template -struct meta_associative_container_traits> - : meta_container_traits< - std::unordered_map, - basic_container, - basic_associative_container, - basic_dynamic_container, - basic_dynamic_associative_container, - dynamic_associative_key_value_container - > -{}; - +template +struct meta_associative_container_traits> + : internal::basic_meta_associative_container_traits> {}; /** * @brief Meta associative container traits for `std::set`s of any type. - * @tparam Key The type of elements. - * @tparam Args Other arguments. + * @tparam Args Template arguments for the container. */ -template -struct meta_associative_container_traits> - : meta_container_traits< - std::set, - basic_container, - basic_associative_container, - basic_dynamic_container, - basic_dynamic_associative_container, - dynamic_associative_key_only_container - > -{}; - +template +struct meta_associative_container_traits> + : internal::basic_meta_associative_container_traits> {}; /** * @brief Meta associative container traits for `std::unordered_set`s of any * type. - * @tparam Key The type of elements. - * @tparam Args Other arguments. + * @tparam Args Template arguments for the container. */ -template -struct meta_associative_container_traits> - : meta_container_traits< - std::unordered_set, - basic_container, - basic_associative_container, - basic_dynamic_container, - basic_dynamic_associative_container, - dynamic_associative_key_only_container - > -{}; +template +struct meta_associative_container_traits> + : internal::basic_meta_associative_container_traits> {}; +/** + * @brief Meta associative container traits for `dense_map`s of any type. + * @tparam Args Template arguments for the container. + */ +template +struct meta_associative_container_traits> + : internal::basic_meta_associative_container_traits> {}; -} +/** + * @brief Meta associative container traits for `dense_set`s of any type. + * @tparam Args Template arguments for the container. + */ +template +struct meta_associative_container_traits> + : internal::basic_meta_associative_container_traits> {}; +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/meta/ctx.hpp b/LiteLoader/third-party/include/entt/meta/ctx.hpp index c577412..5eb1170 100644 --- a/LiteLoader/third-party/include/entt/meta/ctx.hpp +++ b/LiteLoader/third-party/include/entt/meta/ctx.hpp @@ -2,8 +2,8 @@ #define ENTT_META_CTX_HPP -#include "third-party/include/entt/core/attribute.h" -#include "third-party/include/entt/config/config.h" +#include "../core/attribute.h" +#include "../config/config.h" namespace entt { diff --git a/LiteLoader/third-party/include/entt/meta/factory.hpp b/LiteLoader/third-party/include/entt/meta/factory.hpp index d67132e..b548ec8 100644 --- a/LiteLoader/third-party/include/entt/meta/factory.hpp +++ b/LiteLoader/third-party/include/entt/meta/factory.hpp @@ -1,205 +1,148 @@ #ifndef ENTT_META_FACTORY_HPP #define ENTT_META_FACTORY_HPP - #include +#include +#include #include #include #include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/fwd.hpp" -#include "third-party/include/entt/core/type_info.hpp" -#include "third-party/include/entt/core/type_traits.hpp" +#include "../config/config.h" +#include "../core/fwd.hpp" +#include "../core/type_info.hpp" +#include "../core/type_traits.hpp" +#include "../locator/locator.hpp" +#include "context.hpp" #include "meta.hpp" #include "node.hpp" #include "policy.hpp" +#include "range.hpp" +#include "resolve.hpp" #include "utility.hpp" - namespace entt { - /** * @cond TURN_OFF_DOXYGEN * Internal details not to be documented. */ - namespace internal { - -template -[[nodiscard]] bool find_if(const Node *candidate, const Node *node) ENTT_NOEXCEPT { - return node && (node == candidate || find_if(candidate, node->next)); +inline decltype(auto) owner(meta_ctx &ctx, const type_info &info) { + auto &&context = internal::meta_context::from(ctx); + ENTT_ASSERT(context.value.contains(info.hash()), "Type not available"); + return context.value[info.hash()]; } +inline meta_base_node &meta_extend(internal::meta_type_node &parent, const id_type id, meta_base_node node) { + return parent.details->base.insert_or_assign(id, std::move(node)).first->second; +} -template -[[nodiscard]] bool find_if_not(const Id id, Node *node, const Node *owner) ENTT_NOEXCEPT { - if constexpr(std::is_pointer_v) { - return node && ((*node->id == *id && node != owner) || find_if_not(id, node->next, owner)); - } else { - return node && ((node->id == id && node != owner) || find_if_not(id, node->next, owner)); +inline meta_conv_node &meta_extend(internal::meta_type_node &parent, const id_type id, meta_conv_node node) { + return parent.details->conv.insert_or_assign(id, std::move(node)).first->second; +} + +inline meta_ctor_node &meta_extend(internal::meta_type_node &parent, const id_type id, meta_ctor_node node) { + return parent.details->ctor.insert_or_assign(id, std::move(node)).first->second; +} + +inline meta_dtor_node &meta_extend(internal::meta_type_node &parent, meta_dtor_node node) { + return (parent.dtor = std::move(node)); +} + +inline meta_data_node &meta_extend(internal::meta_type_node &parent, const id_type id, meta_data_node node) { + return parent.details->data.insert_or_assign(id, std::move(node)).first->second; +} + +inline meta_func_node &meta_extend(internal::meta_type_node &parent, const id_type id, meta_func_node node) { + if(auto it = parent.details->func.find(id); it != parent.details->func.end()) { + for(auto *curr = &it->second; curr; curr = curr->next.get()) { + if(curr->invoke == node.invoke) { + node.next = std::move(curr->next); + *curr = std::move(node); + return *curr; + } + } + + // locally overloaded function + node.next = std::make_shared(std::move(parent.details->func[id])); } + + return parent.details->func.insert_or_assign(id, std::move(node)).first->second; } - +inline meta_prop_node &meta_extend(dense_map &prop, const id_type id, meta_prop_node node) { + return (prop[id] = std::move(node)); } +} // namespace internal /** * Internal details not to be documented. * @endcond */ - -/** - * @brief Meta factory to be used for reflection purposes. - * - * The meta factory is an utility class used to reflect types, data members and - * functions of all sorts. This class ensures that the underlying web of types - * is built correctly and performs some checks in debug mode to ensure that - * there are no subtle errors at runtime. - */ -template -struct meta_factory; - - -/** - * @brief Extended meta factory to be used for reflection purposes. - * @tparam Type Reflected type for which the factory was created. - * @tparam Spec Property specialization pack used to disambiguate overloads. - */ -template -struct meta_factory: public meta_factory { -private: - template - void unpack(std::index_sequence, std::tuple property, Other &&... other) { - unroll(choice<3>, std::move(std::get(property))..., std::forward(other)...); - } - - template - void unroll(choice_t<3>, std::tuple property, Other &&... other) { - unpack(std::index_sequence_for{}, std::move(property), std::forward(other)...); - } - - template - void unroll(choice_t<2>, std::pair property, Other &&... other) { - assign(std::move(property.first), std::move(property.second)); - unroll(choice<3>, std::forward(other)...); - } - - template - std::enable_if_t> - unroll(choice_t<1>, Property &&property, Other &&... other) { - assign(std::forward(property)); - unroll(choice<3>, std::forward(other)...); - } - - template - void unroll(choice_t<0>, Func &&invocable, Other &&... other) { - unroll(choice<3>, std::forward(invocable)(), std::forward(other)...); - } - - template - void unroll(choice_t<0>) {} - - template - void assign(Key &&key, meta_any value = {}) { - static meta_any property[2u]{}; - - static internal::meta_prop_node node{ - nullptr, - property[0u], - property[1u] - }; - - entt::meta_any instance{std::forward(key)}; - ENTT_ASSERT(!internal::find_if_not(&instance, *curr, &node), "Duplicate key"); - property[0u] = std::move(instance); - property[1u] = std::move(value); - - if(!internal::find_if(&node, *curr)) { - node.next = *curr; - *curr = &node; - } - } - -public: - /** - * @brief Constructs an extended factory from a given node. - * @param target The underlying node to which to assign the properties. - */ - meta_factory(internal::meta_prop_node **target) ENTT_NOEXCEPT - : curr{target} - {} - - /** - * @brief Assigns a property to the last meta object created. - * - * Both the key and the value (if any) must be at least copy constructible. - * - * @tparam PropertyOrKey Type of the property or property key. - * @tparam Value Optional type of the property value. - * @param property_or_key Property or property key. - * @param value Optional property value. - * @return A meta factory for the parent type. - */ - template - auto prop(PropertyOrKey &&property_or_key, Value &&... value) && { - if constexpr(sizeof...(Value) == 0) { - unroll(choice<3>, std::forward(property_or_key)); - } else { - assign(std::forward(property_or_key), std::forward(value)...); - } - - return meta_factory{curr}; - } - - /** - * @brief Assigns properties to the last meta object created. - * - * Both the keys and the values (if any) must be at least copy - * constructible. - * - * @tparam Property Types of the properties. - * @param property Properties to assign to the last meta object created. - * @return A meta factory for the parent type. - */ - template - auto props(Property... property) && { - unroll(choice<3>, std::forward(property)...); - return meta_factory{curr}; - } - -private: - internal::meta_prop_node **curr; -}; - - /** * @brief Basic meta factory to be used for reflection purposes. * @tparam Type Reflected type for which the factory was created. */ template -struct meta_factory { +class meta_factory { + template + void data(const id_type id, std::index_sequence) noexcept { + using data_type = std::invoke_result_t; + using args_type = type_list)>::args_type...>; + static_assert(Policy::template value, "Invalid return type for the given policy"); + + auto &&elem = internal::meta_extend( + internal::owner(*ctx, *info), + id, + internal::meta_data_node{ + /* this is never static */ + (std::is_member_object_pointer_v)> && ... && std::is_const_v>) ? internal::meta_traits::is_const : internal::meta_traits::is_none, + Setter::size, + &internal::resolve>>, + &meta_arg::size != 1u, type_list_element_t>...>>, + +[](meta_handle instance, meta_any value) { return (meta_setter>(*instance.operator->(), value.as_ref()) || ...); }, + &meta_getter}); + + bucket = &elem.prop; + } + +public: + /*! @brief Default constructor. */ + meta_factory() noexcept + : meta_factory{locator::value_or()} {} + /** - * @brief Makes a meta type _searchable_. - * @param id Optional unique identifier. - * @return An extended meta factory for the given type. + * @brief Context aware constructor. + * @param area The context into which to construct meta types. */ - auto type(const id_type id = type_hash::value()) { - auto * const node = internal::meta_info::resolve(); + meta_factory(meta_ctx &area) noexcept + : ctx{&area}, + bucket{}, + info{&type_id()} { + auto &&elem = internal::owner(*ctx, *info); - ENTT_ASSERT(!internal::find_if_not(id, *internal::meta_context::global(), node), "Duplicate identifier"); - node->id = id; - - if(!internal::find_if(node, *internal::meta_context::global())) { - node->next = *internal::meta_context::global(); - *internal::meta_context::global() = node; + if(!elem.details) { + elem.details = std::make_shared(); } - return meta_factory{&node->prop}; + bucket = &elem.details->prop; + } + + /** + * @brief Assigns a custom unique identifier to a meta type. + * @param id A custom unique identifier. + * @return An extended meta factory for the given type. + */ + auto type(const id_type id) noexcept { + auto &&elem = internal::owner(*ctx, *info); + ENTT_ASSERT(elem.id == id || !resolve(*ctx, id), "Duplicate identifier"); + bucket = &elem.details->prop; + elem.id = id; + return *this; } /** @@ -211,25 +154,20 @@ struct meta_factory { * @return A meta factory for the parent type. */ template - auto base() ENTT_NOEXCEPT { - static_assert(std::is_base_of_v, "Invalid base type"); - auto * const type = internal::meta_info::resolve(); + auto base() noexcept { + static_assert(!std::is_same_v && std::is_base_of_v, "Invalid base type"); - static internal::meta_base_node node{ - type, - nullptr, - &internal::meta_info::resolve, - [](const void *instance) ENTT_NOEXCEPT -> const void * { - return static_cast(static_cast(instance)); - } - }; + internal::meta_extend( + internal::owner(*ctx, *info), + type_id().hash(), + internal::meta_base_node{ + &internal::resolve, + +[](const void *instance) noexcept { + return static_cast(static_cast(static_cast(instance))); + }}); - if(!internal::find_if(&node, type->base)) { - node.next = type->base; - type->base = &node; - } - - return meta_factory{}; + bucket = nullptr; + return *this; } /** @@ -245,48 +183,19 @@ struct meta_factory { * @return A meta factory for the parent type. */ template - std::enable_if_t, meta_factory> conv() ENTT_NOEXCEPT { - using conv_type = std::invoke_result_t; - auto * const type = internal::meta_info::resolve(); + auto conv() noexcept { + using conv_type = std::remove_cv_t>>; - static internal::meta_conv_node node{ - type, - nullptr, - &internal::meta_info::resolve, - [](const void *instance) -> meta_any { - return (static_cast(instance)->*Candidate)(); - } - }; + internal::meta_extend( + internal::owner(*ctx, *info), + type_id().hash(), + internal::meta_conv_node{ + +[](const meta_ctx &area, const void *instance) { + return forward_as_meta(area, std::invoke(Candidate, *static_cast(instance))); + }}); - if(!internal::find_if(&node, type->conv)) { - node.next = type->conv; - type->conv = &node; - } - - return meta_factory{}; - } - - /*! @copydoc conv */ - template - std::enable_if_t, meta_factory> conv() ENTT_NOEXCEPT { - using conv_type = std::invoke_result_t; - auto * const type = internal::meta_info::resolve(); - - static internal::meta_conv_node node{ - type, - nullptr, - &internal::meta_info::resolve, - [](const void *instance) -> meta_any { - return Candidate(*static_cast(instance)); - } - }; - - if(!internal::find_if(&node, type->conv)) { - node.next = type->conv; - type->conv = &node; - } - - return meta_factory{}; + bucket = nullptr; + return *this; } /** @@ -299,25 +208,19 @@ struct meta_factory { * @return A meta factory for the parent type. */ template - auto conv() ENTT_NOEXCEPT { - static_assert(std::is_convertible_v, "Could not convert to the required type"); - auto * const type = internal::meta_info::resolve(); + auto conv() noexcept { + using conv_type = std::remove_cv_t>; - static internal::meta_conv_node node{ - type, - nullptr, - &internal::meta_info::resolve, - [](const void *instance) -> meta_any { - return static_cast(*static_cast(instance)); - } - }; + internal::meta_extend( + internal::owner(*ctx, *info), + type_id().hash(), + internal::meta_conv_node{ + +[](const meta_ctx &area, const void *instance) { + return forward_as_meta(area, static_cast(*static_cast(instance))); + }}); - if(!internal::find_if(&node, type->conv)) { - node.next = type->conv; - type->conv = &node; - } - - return meta_factory{}; + bucket = nullptr; + return *this; } /** @@ -334,30 +237,21 @@ struct meta_factory { * @return An extended meta factory for the parent type. */ template - auto ctor() ENTT_NOEXCEPT { + auto ctor() noexcept { using descriptor = meta_function_helper_t; - static_assert(std::is_same_v, Type>, "The function doesn't return an object of the required type"); - auto * const type = internal::meta_info::resolve(); + static_assert(Policy::template value, "Invalid return type for the given policy"); + static_assert(std::is_same_v>, Type>, "The function doesn't return an object of the required type"); - static internal::meta_ctor_node node{ - type, - nullptr, - nullptr, - descriptor::args_type::size, - [](const typename internal::meta_ctor_node::size_type index) ENTT_NOEXCEPT { - return meta_arg(typename descriptor::args_type{}, index); - }, - [](meta_any * const args) { - return meta_invoke({}, args, std::make_index_sequence{}); - } - }; + internal::meta_extend( + internal::owner(*ctx, *info), + type_id().hash(), + internal::meta_ctor_node{ + descriptor::args_type::size, + &meta_arg, + &meta_construct}); - if(!internal::find_if(&node, type->ctor)) { - node.next = type->ctor; - type->ctor = &node; - } - - return meta_factory>{&node.prop}; + bucket = nullptr; + return *this; } /** @@ -371,41 +265,36 @@ struct meta_factory { * @return An extended meta factory for the parent type. */ template - auto ctor() ENTT_NOEXCEPT { - using descriptor = meta_function_helper_t; - auto * const type = internal::meta_info::resolve(); + auto ctor() noexcept { + // default constructor is already implicitly generated, no need for redundancy + if constexpr(sizeof...(Args) != 0u) { + using descriptor = meta_function_helper_t; - static internal::meta_ctor_node node{ - type, - nullptr, - nullptr, - descriptor::args_type::size, - [](const typename internal::meta_ctor_node::size_type index) ENTT_NOEXCEPT { - return meta_arg(typename descriptor::args_type{}, index); - }, - [](meta_any * const args) { - return meta_construct(args, std::make_index_sequence{}); - } - }; - - if(!internal::find_if(&node, type->ctor)) { - node.next = type->ctor; - type->ctor = &node; + internal::meta_extend( + internal::owner(*ctx, *info), + type_id().hash(), + internal::meta_ctor_node{ + descriptor::args_type::size, + &meta_arg, + &meta_construct}); } - return meta_factory{&node.prop}; + bucket = nullptr; + return *this; } /** * @brief Assigns a meta destructor to a meta type. * - * Free functions can be assigned to meta types in the role of destructors. - * The signature of the function should identical to the following: + * Both free functions and member functions can be assigned to meta types in + * the role of destructors.
+ * The signature of a free function should be identical to the following: * * @code{.cpp} * void(Type &); * @endcode * + * Member functions should not take arguments instead.
* The purpose is to give users the ability to free up resources that * require special treatment before an object is actually destroyed. * @@ -413,15 +302,16 @@ struct meta_factory { * @return A meta factory for the parent type. */ template - auto dtor() ENTT_NOEXCEPT { + auto dtor() noexcept { static_assert(std::is_invocable_v, "The function doesn't accept an object of the type provided"); - auto * const type = internal::meta_info::resolve(); - type->dtor = [](void *instance) { - Func(*static_cast(instance)); - }; + internal::meta_extend( + internal::owner(*ctx, *info), + internal::meta_dtor_node{ + +[](void *instance) { std::invoke(Func, *static_cast(instance)); }}); - return meta_factory{}; + bucket = nullptr; + return *this; } /** @@ -438,35 +328,41 @@ struct meta_factory { * @return An extended meta factory for the parent type. */ template - auto data(const id_type id) ENTT_NOEXCEPT { + auto data(const id_type id) noexcept { if constexpr(std::is_member_object_pointer_v) { - return data(id); + using data_type = std::remove_reference_t>; + + auto &&elem = internal::meta_extend( + internal::owner(*ctx, *info), + id, + internal::meta_data_node{ + /* this is never static */ + std::is_const_v ? internal::meta_traits::is_const : internal::meta_traits::is_none, + 1u, + &internal::resolve>, + &meta_arg>>, + &meta_setter, + &meta_getter}); + + bucket = &elem.prop; } else { - using data_type = std::remove_pointer_t; - auto * const type = internal::meta_info::resolve(); + using data_type = std::remove_reference_t>; - static internal::meta_data_node node{ - {}, - type, - nullptr, - nullptr, - std::is_same_v || std::is_const_v, - true, - &internal::meta_info::resolve, - &meta_setter, - &meta_getter - }; + auto &&elem = internal::meta_extend( + internal::owner(*ctx, *info), + id, + internal::meta_data_node{ + ((std::is_same_v> || std::is_const_v) ? internal::meta_traits::is_const : internal::meta_traits::is_none) | internal::meta_traits::is_static, + 1u, + &internal::resolve>, + &meta_arg>>, + &meta_setter, + &meta_getter}); - ENTT_ASSERT(!internal::find_if_not(id, type->data, &node), "Duplicate identifier"); - node.id = id; - - if(!internal::find_if(&node, type->data)) { - node.next = type->data; - type->data = &node; - } - - return meta_factory>{&node.prop}; + bucket = &elem.prop; } + + return *this; } /** @@ -490,35 +386,70 @@ struct meta_factory { * @return An extended meta factory for the parent type. */ template - auto data(const id_type id) ENTT_NOEXCEPT { - using underlying_type = std::remove_reference_t>; - auto * const type = internal::meta_info::resolve(); + auto data(const id_type id) noexcept { + using data_type = std::invoke_result_t; + static_assert(Policy::template value, "Invalid return type for the given policy"); - static internal::meta_data_node node{ - {}, - type, - nullptr, - nullptr, - std::is_same_v || (std::is_member_object_pointer_v && std::is_const_v), - false, - &internal::meta_info::resolve, - &meta_setter, - &meta_getter - }; + if constexpr(std::is_same_v) { + auto &&elem = internal::meta_extend( + internal::owner(*ctx, *info), + id, + internal::meta_data_node{ + /* this is never static */ + internal::meta_traits::is_const, + 0u, + &internal::resolve>>, + &meta_arg>, + &meta_setter, + &meta_getter}); - ENTT_ASSERT(!internal::find_if_not(id, type->data, &node), "Duplicate identifier"); - node.id = id; + bucket = &elem.prop; + } else { + using args_type = typename meta_function_helper_t::args_type; - if(!internal::find_if(&node, type->data)) { - node.next = type->data; - type->data = &node; + auto &&elem = internal::meta_extend( + internal::owner(*ctx, *info), + id, + internal::meta_data_node{ + /* this is never static nor const */ + internal::meta_traits::is_none, + 1u, + &internal::resolve>>, + &meta_arg>>, + &meta_setter, + &meta_getter}); + + bucket = &elem.prop; } - return meta_factory, std::integral_constant>{&node.prop}; + return *this; } /** - * @brief Assigns a meta funcion to a meta type. + * @brief Assigns a meta data to a meta type by means of its setters and + * getter. + * + * Multi-setter support for meta data members. All setters are tried in the + * order of definition before returning to the caller.
+ * Setters can be either free functions, member functions or a mix of them + * and are provided via a `value_list` type. + * + * @sa data + * + * @tparam Setter The actual functions to use as setters. + * @tparam Getter The actual getter function. + * @tparam Policy Optional policy (no policy set by default). + * @param id Unique identifier. + * @return An extended meta factory for the parent type. + */ + template + auto data(const id_type id) noexcept { + data(id, std::make_index_sequence{}); + return *this; + } + + /** + * @brief Assigns a meta function to a meta type. * * Both member functions and free functions can be assigned to a meta * type.
@@ -531,46 +462,81 @@ struct meta_factory { * @return An extended meta factory for the parent type. */ template - auto func(const id_type id) ENTT_NOEXCEPT { + auto func(const id_type id) noexcept { using descriptor = meta_function_helper_t; - auto * const type = internal::meta_info::resolve(); + static_assert(Policy::template value, "Invalid return type for the given policy"); - static internal::meta_func_node node{ - {}, - type, - nullptr, - nullptr, - descriptor::args_type::size, - descriptor::is_const, - descriptor::is_static, - &internal::meta_info, void, typename descriptor::return_type>>::resolve, - [](const typename internal::meta_func_node::size_type index) ENTT_NOEXCEPT { - return meta_arg(typename descriptor::args_type{}, index); - }, - [](meta_handle instance, meta_any *args) { - return meta_invoke(std::move(instance), args, std::make_index_sequence{}); - } - }; + auto &&elem = internal::meta_extend( + internal::owner(*ctx, *info), + id, + internal::meta_func_node{ + (descriptor::is_const ? internal::meta_traits::is_const : internal::meta_traits::is_none) | (descriptor::is_static ? internal::meta_traits::is_static : internal::meta_traits::is_none), + descriptor::args_type::size, + &internal::resolve, void, std::remove_cv_t>>>, + &meta_arg, + &meta_invoke}); - for(auto *it = &type->func; *it; it = &(*it)->next) { - if(*it == &node) { - *it = node.next; - break; - } + bucket = &elem.prop; + return *this; + } + + /** + * @brief Assigns a property to the last meta object created. + * + * Both the key and the value (if any) must be at least copy constructible. + * + * @tparam Value Optional type of the property value. + * @param id Property key. + * @param value Optional property value. + * @return An extended meta factory for the given type. + */ + template + meta_factory prop(id_type id, [[maybe_unused]] Value &&...value) { + ENTT_ASSERT(bucket != nullptr, "Meta object does not support properties"); + + if constexpr(sizeof...(Value) == 0u) { + internal::meta_extend( + *bucket, + id, + internal::meta_prop_node{ + &internal::resolve}); + } else { + internal::meta_extend( + *bucket, + id, + internal::meta_prop_node{ + &internal::resolve>..., + std::make_shared>(std::forward(value))...}); } - internal::meta_func_node **it = &type->func; - for(; *it && (*it)->id != id; it = &(*it)->next); - for(; *it && (*it)->id == id && (*it)->arity < node.arity; it = &(*it)->next); - - node.id = id; - node.next = *it; - *it = &node; - - return meta_factory>{&node.prop}; + return *this; } + +private: + meta_ctx *ctx; + dense_map *bucket; + const type_info *info; }; +/** + * @brief Utility function to use for reflection. + * + * This is the point from which everything starts.
+ * By invoking this function with a type that is not yet reflected, a meta type + * is created to which it will be possible to attach meta objects through a + * dedicated factory. + * + * @tparam Type Type to reflect. + * @param ctx The context into which to construct meta types. + * @return A meta factory for the given type. + */ +template +[[nodiscard]] auto meta(meta_ctx &ctx) noexcept { + auto &&context = internal::meta_context::from(ctx); + // make sure the type exists in the context before returning a factory + context.value.try_emplace(type_id().hash(), internal::resolve(context)); + return meta_factory{ctx}; +} /** * @brief Utility function to use for reflection. @@ -584,14 +550,94 @@ struct meta_factory { * @return A meta factory for the given type. */ template -[[nodiscard]] auto meta() ENTT_NOEXCEPT { - auto * const node = internal::meta_info::resolve(); - // extended meta factory to allow assigning properties to opaque meta types - return meta_factory{&node->prop}; +[[nodiscard]] auto meta() noexcept { + return meta(locator::value_or()); } +/** + * @brief Resets a type and all its parts. + * + * Resets a type and all its data members, member functions and properties, as + * well as its constructors, destructors and conversion functions if any.
+ * Base classes aren't reset but the link between the two types is removed. + * + * The type is also removed from the set of searchable types. + * + * @param id Unique identifier. + * @param ctx The context from which to reset meta types. + */ +inline void meta_reset(meta_ctx &ctx, const id_type id) noexcept { + auto &&context = internal::meta_context::from(ctx); + for(auto it = context.value.begin(); it != context.value.end();) { + if(it->second.id == id) { + it = context.value.erase(it); + } else { + ++it; + } + } } +/** + * @brief Resets a type and all its parts. + * + * Resets a type and all its data members, member functions and properties, as + * well as its constructors, destructors and conversion functions if any.
+ * Base classes aren't reset but the link between the two types is removed. + * + * The type is also removed from the set of searchable types. + * + * @param id Unique identifier. + */ +inline void meta_reset(const id_type id) noexcept { + meta_reset(locator::value_or(), id); +} + +/** + * @brief Resets a type and all its parts. + * + * @sa meta_reset + * + * @tparam Type Type to reset. + * @param ctx The context from which to reset meta types. + */ +template +void meta_reset(meta_ctx &ctx) noexcept { + internal::meta_context::from(ctx).value.erase(type_id().hash()); +} + +/** + * @brief Resets a type and all its parts. + * + * @sa meta_reset + * + * @tparam Type Type to reset. + */ +template +void meta_reset() noexcept { + meta_reset(locator::value_or()); +} + +/** + * @brief Resets all meta types. + * + * @sa meta_reset + * + * @param ctx The context from which to reset meta types. + */ +inline void meta_reset(meta_ctx &ctx) noexcept { + internal::meta_context::from(ctx).value.clear(); +} + +/** + * @brief Resets all meta types. + * + * @sa meta_reset + */ +inline void meta_reset() noexcept { + meta_reset(locator::value_or()); +} + +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/meta/meta.hpp b/LiteLoader/third-party/include/entt/meta/meta.hpp index 63c9a03..f8cb917 100644 --- a/LiteLoader/third-party/include/entt/meta/meta.hpp +++ b/LiteLoader/third-party/include/entt/meta/meta.hpp @@ -1,38 +1,33 @@ #ifndef ENTT_META_META_HPP #define ENTT_META_META_HPP - #include -#include #include #include #include #include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/any.hpp" -#include "third-party/include/entt/core/fwd.hpp" -#include "third-party/include/entt/core/utility.hpp" -#include "third-party/include/entt/core/type_info.hpp" -#include "third-party/include/entt/core/type_traits.hpp" +#include "../config/config.h" +#include "../core/any.hpp" +#include "../core/fwd.hpp" +#include "../core/iterator.hpp" +#include "../core/type_info.hpp" +#include "../core/type_traits.hpp" +#include "../core/utility.hpp" +#include "../locator/locator.hpp" #include "adl_pointer.hpp" -#include "ctx.hpp" +#include "context.hpp" +#include "fwd.hpp" #include "node.hpp" #include "range.hpp" #include "type_traits.hpp" - namespace entt { - class meta_any; class meta_type; - /*! @brief Proxy object for sequence containers. */ class meta_sequence_container { - template - struct meta_sequence_container_proxy; - class meta_iterator; public: @@ -41,58 +36,51 @@ public: /*! @brief Meta iterator type. */ using iterator = meta_iterator; - /*! @brief Default constructor. */ - meta_sequence_container() ENTT_NOEXCEPT = default; + /** + * @brief Context aware constructor. + * @param area The context from which to search for meta types. + */ + meta_sequence_container(const meta_ctx &area = locator::value_or()) noexcept + : ctx{&area} {} /** - * @brief Construct a proxy object for sequence containers. + * @brief Rebinds a proxy object to a sequence container type. * @tparam Type Type of container to wrap. * @param instance The container to wrap. */ template - meta_sequence_container(std::in_place_type_t, any instance) ENTT_NOEXCEPT - : value_type_fn{&meta_sequence_container_proxy::value_type}, - size_fn{&meta_sequence_container_proxy::size}, - resize_fn{&meta_sequence_container_proxy::resize}, - clear_fn{&meta_sequence_container_proxy::clear}, - begin_fn{&meta_sequence_container_proxy::begin}, - end_fn{&meta_sequence_container_proxy::end}, - insert_fn{&meta_sequence_container_proxy::insert}, - erase_fn{&meta_sequence_container_proxy::erase}, - get_fn{&meta_sequence_container_proxy::get}, - storage{std::move(instance)} - {} + void rebind(any instance) noexcept { + value_type_node = &internal::resolve; + size_fn = &meta_sequence_container_traits::size; + resize_fn = &meta_sequence_container_traits::resize; + iter_fn = &meta_sequence_container_traits::iter; + insert_or_erase_fn = &meta_sequence_container_traits::insert_or_erase; + storage = std::move(instance); + } - [[nodiscard]] inline meta_type value_type() const ENTT_NOEXCEPT; - [[nodiscard]] inline size_type size() const ENTT_NOEXCEPT; - inline bool resize(size_type); + [[nodiscard]] inline meta_type value_type() const noexcept; + [[nodiscard]] inline size_type size() const noexcept; + inline bool resize(const size_type); inline bool clear(); [[nodiscard]] inline iterator begin(); [[nodiscard]] inline iterator end(); - inline std::pair insert(iterator, meta_any); - inline std::pair erase(iterator); - [[nodiscard]] inline meta_any operator[](size_type); - [[nodiscard]] inline explicit operator bool() const ENTT_NOEXCEPT; + inline iterator insert(iterator, meta_any); + inline iterator erase(iterator); + [[nodiscard]] inline meta_any operator[](const size_type); + [[nodiscard]] inline explicit operator bool() const noexcept; private: - meta_type(* value_type_fn)() ENTT_NOEXCEPT = nullptr; - size_type(* size_fn)(const any &) ENTT_NOEXCEPT = nullptr; - bool(* resize_fn)(any &, size_type) = nullptr; - bool(* clear_fn)(any &) = nullptr; - iterator(* begin_fn)(any &) = nullptr; - iterator(* end_fn)(any &) = nullptr; - std::pair(* insert_fn)(any &, iterator, meta_any &) = nullptr; - std::pair(* erase_fn)(any &, iterator) = nullptr; - meta_any(* get_fn)(any &, size_type) = nullptr; + const meta_ctx *ctx{}; + internal::meta_type_node (*value_type_node)(const internal::meta_context &){}; + size_type (*size_fn)(const any &) noexcept {}; + bool (*resize_fn)(any &, size_type){}; + iterator (*iter_fn)(const meta_ctx &, any &, const bool){}; + iterator (*insert_or_erase_fn)(const meta_ctx &, any &, const any &, meta_any &){}; any storage{}; }; - /*! @brief Proxy object for associative containers. */ class meta_associative_container { - template - struct meta_associative_container_proxy; - class meta_iterator; public: @@ -101,115 +89,136 @@ public: /*! @brief Meta iterator type. */ using iterator = meta_iterator; - /*! @brief Default constructor. */ - meta_associative_container() ENTT_NOEXCEPT = default; + /** + * @brief Context aware constructor. + * @param area The context from which to search for meta types. + */ + meta_associative_container(const meta_ctx &area = locator::value_or()) noexcept + : ctx{&area} {} /** - * @brief Construct a proxy object for associative containers. + * @brief Rebinds a proxy object to an associative container type. * @tparam Type Type of container to wrap. * @param instance The container to wrap. */ template - meta_associative_container(std::in_place_type_t, any instance) ENTT_NOEXCEPT - : key_only_container{is_key_only_meta_associative_container_v}, - key_type_fn{&meta_associative_container_proxy::key_type}, - mapped_type_fn{&meta_associative_container_proxy::mapped_type}, - value_type_fn{&meta_associative_container_proxy::value_type}, - size_fn{&meta_associative_container_proxy::size}, - clear_fn{&meta_associative_container_proxy::clear}, - begin_fn{&meta_associative_container_proxy::begin}, - end_fn{&meta_associative_container_proxy::end}, - insert_fn{&meta_associative_container_proxy::insert}, - erase_fn{&meta_associative_container_proxy::erase}, - find_fn{&meta_associative_container_proxy::find}, - storage{std::move(instance)} - {} + void rebind(any instance) noexcept { + if constexpr(!meta_associative_container_traits::key_only) { + mapped_type_node = &internal::resolve; + } - [[nodiscard]] inline bool key_only() const ENTT_NOEXCEPT; - [[nodiscard]] inline meta_type key_type() const ENTT_NOEXCEPT; - [[nodiscard]] inline meta_type mapped_type() const ENTT_NOEXCEPT; - [[nodiscard]] inline meta_type value_type() const ENTT_NOEXCEPT; - [[nodiscard]] inline size_type size() const ENTT_NOEXCEPT; + key_only_container = meta_associative_container_traits::key_only; + key_type_node = &internal::resolve; + value_type_node = &internal::resolve; + size_fn = &meta_associative_container_traits::size; + clear_fn = &meta_associative_container_traits::clear; + iter_fn = &meta_associative_container_traits::iter; + insert_or_erase_fn = &meta_associative_container_traits::insert_or_erase; + find_fn = &meta_associative_container_traits::find; + storage = std::move(instance); + } + + [[nodiscard]] inline bool key_only() const noexcept; + [[nodiscard]] inline meta_type key_type() const noexcept; + [[nodiscard]] inline meta_type mapped_type() const noexcept; + [[nodiscard]] inline meta_type value_type() const noexcept; + [[nodiscard]] inline size_type size() const noexcept; inline bool clear(); [[nodiscard]] inline iterator begin(); [[nodiscard]] inline iterator end(); + inline bool insert(meta_any); inline bool insert(meta_any, meta_any); - inline bool erase(meta_any); + inline size_type erase(meta_any); [[nodiscard]] inline iterator find(meta_any); - [[nodiscard]] inline explicit operator bool() const ENTT_NOEXCEPT; + [[nodiscard]] inline explicit operator bool() const noexcept; private: + const meta_ctx *ctx{}; bool key_only_container{}; - meta_type(* key_type_fn)() ENTT_NOEXCEPT = nullptr; - meta_type(* mapped_type_fn)() ENTT_NOEXCEPT = nullptr; - meta_type(* value_type_fn)() ENTT_NOEXCEPT = nullptr; - size_type(* size_fn)(const any &) ENTT_NOEXCEPT = nullptr; - bool(* clear_fn)(any &) = nullptr; - iterator(* begin_fn)(any &) = nullptr; - iterator(* end_fn)(any &) = nullptr; - bool(* insert_fn)(any &, meta_any &, meta_any &) = nullptr; - bool(* erase_fn)(any &, meta_any &) = nullptr; - iterator(* find_fn)(any &, meta_any &) = nullptr; + internal::meta_type_node (*key_type_node)(const internal::meta_context &){}; + internal::meta_type_node (*mapped_type_node)(const internal::meta_context &){}; + internal::meta_type_node (*value_type_node)(const internal::meta_context &){}; + size_type (*size_fn)(const any &) noexcept {}; + bool (*clear_fn)(any &){}; + iterator (*iter_fn)(const meta_ctx &, any &, const bool){}; + size_type (*insert_or_erase_fn)(any &, meta_any &, meta_any &){}; + iterator (*find_fn)(const meta_ctx &, any &, meta_any &){}; any storage{}; }; - /*! @brief Opaque wrapper for values of any type. */ class meta_any { - enum class operation { DTOR, DEREF, SEQ, ASSOC }; + enum class operation : std::uint8_t { + deref, + seq, + assoc + }; using vtable_type = void(const operation, const any &, void *); template - static void basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const any &from, [[maybe_unused]] void *to) { - static_assert(std::is_same_v>, Type>, "Invalid type"); + static void basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const any &value, [[maybe_unused]] void *other) { + static_assert(std::is_same_v>, Type>, "Invalid type"); if constexpr(!std::is_void_v) { switch(op) { - case operation::DTOR: - if(auto *curr = static_cast(to); curr->dtor && from.owner()) { - curr->dtor(const_cast(from).data()); - } - break; - case operation::DEREF: + case operation::deref: if constexpr(is_meta_pointer_like_v) { - using element_type = std::remove_const_t::element_type>; - - if constexpr(std::is_function_v) { - *static_cast(to) = any_cast(from); + if constexpr(std::is_function_v::element_type>) { + static_cast(other)->emplace(any_cast(value)); } else if constexpr(!std::is_same_v::element_type>, void>) { - using in_place_type = decltype(adl_meta_pointer_like::dereference(any_cast(from))); - static_cast(to)->emplace(adl_meta_pointer_like::dereference(any_cast(from))); + using in_place_type = decltype(adl_meta_pointer_like::dereference(any_cast(value))); + + if constexpr(std::is_constructible_v) { + if(const auto &pointer_like = any_cast(value); pointer_like) { + static_cast(other)->emplace(adl_meta_pointer_like::dereference(pointer_like)); + } + } else { + static_cast(other)->emplace(adl_meta_pointer_like::dereference(any_cast(value))); + } } } break; - case operation::SEQ: + case operation::seq: if constexpr(is_complete_v>) { - *static_cast(to) = { std::in_place_type, std::move(const_cast(from)) }; + static_cast(other)->rebind(std::move(const_cast(value))); } break; - case operation::ASSOC: + case operation::assoc: if constexpr(is_complete_v>) { - *static_cast(to) = { std::in_place_type, std::move(const_cast(from)) }; + static_cast(other)->rebind(std::move(const_cast(value))); } break; } } } - meta_any(const meta_any &other, any ref) ENTT_NOEXCEPT + void release() { + if(node.dtor.dtor && owner()) { + node.dtor.dtor(storage.data()); + } + } + + meta_any(const meta_ctx &area, const meta_any &other, any ref) noexcept : storage{std::move(ref)}, - node{storage ? other.node : nullptr}, - vtable{storage ? other.vtable : &basic_vtable} - {} + ctx{&area}, + node{storage ? other.node : internal::meta_type_node{}}, + vtable{storage ? other.vtable : &basic_vtable} {} public: - /*! @brief Default constructor. */ - meta_any() ENTT_NOEXCEPT + /*! Default constructor. */ + meta_any() noexcept + : meta_any{meta_ctx_arg, locator::value_or()} {} + + /** + * @brief Context aware constructor. + * @param area The context from which to search for meta types. + */ + meta_any(meta_ctx_arg_t, const meta_ctx &area) noexcept : storage{}, + ctx{&area}, node{}, - vtable{&basic_vtable} - {} + vtable{&basic_vtable} {} /** * @brief Constructs a wrapper by directly initializing the new object. @@ -218,24 +227,22 @@ public: * @param args Parameters to use to construct the instance. */ template - explicit meta_any(std::in_place_type_t, Args &&... args) - : storage{std::in_place_type, std::forward(args)...}, - node{internal::meta_info::resolve()}, - vtable{&basic_vtable>>} - {} + explicit meta_any(std::in_place_type_t, Args &&...args) + : meta_any{locator::value_or(), std::in_place_type, std::forward(args)...} {} /** - * @brief Constructs a wrapper that holds an unmanaged object. + * @brief Constructs a wrapper by directly initializing the new object. * @tparam Type Type of object to use to initialize the wrapper. - * @param value An instance of an object to use to initialize the wrapper. + * @tparam Args Types of arguments to use to construct the new instance. + * @param area The context from which to search for meta types. + * @param args Parameters to use to construct the instance. */ - template - meta_any(std::reference_wrapper value) - : meta_any{} - { - // invokes deprecated assignment operator (and avoids issues with vs2017) - *this = value; - } + template + explicit meta_any(const meta_ctx &area, std::in_place_type_t, Args &&...args) + : storage{std::in_place_type, std::forward(args)...}, + ctx{&area}, + node{internal::resolve>>(internal::meta_context::from(*ctx))}, + vtable{&basic_vtable>>} {} /** * @brief Constructs a wrapper from a given value. @@ -244,10 +251,39 @@ public: */ template, meta_any>>> meta_any(Type &&value) - : storage{std::forward(value)}, - node{internal::meta_info>::resolve()}, - vtable{&basic_vtable>} - {} + : meta_any{locator::value_or(), std::forward(value)} {} + + /** + * @brief Constructs a wrapper from a given value. + * @tparam Type Type of object to use to initialize the wrapper. + * @param area The context from which to search for meta types. + * @param value An instance of an object to use to initialize the wrapper. + */ + template, meta_any>>> + meta_any(const meta_ctx &area, Type &&value) + : meta_any{area, std::in_place_type>, std::forward(value)} {} + + /** + * @brief Context aware copy constructor. + * @param area The context from which to search for meta types. + * @param other The instance to copy from. + */ + meta_any(const meta_ctx &area, const meta_any &other) + : meta_any{other} { + ctx = &area; + node = node.resolve ? node.resolve(internal::meta_context::from(*ctx)) : node; + } + + /** + * @brief Context aware move constructor. + * @param area The context from which to search for meta types. + * @param other The instance to move from. + */ + meta_any(const meta_ctx &area, meta_any &&other) + : meta_any{std::move(other)} { + ctx = &area; + node = node.resolve ? node.resolve(internal::meta_context::from(*ctx)) : node; + } /** * @brief Copy constructor. @@ -259,15 +295,15 @@ public: * @brief Move constructor. * @param other The instance to move from. */ - meta_any(meta_any &&other) ENTT_NOEXCEPT + meta_any(meta_any &&other) noexcept : storage{std::move(other.storage)}, - node{std::exchange(other.node, nullptr)}, - vtable{std::exchange(other.vtable, &basic_vtable)} - {} + ctx{other.ctx}, + node{std::exchange(other.node, internal::meta_type_node{})}, + vtable{std::exchange(other.vtable, &basic_vtable)} {} /*! @brief Frees the internal storage, whatever it means. */ ~meta_any() { - vtable(operation::DTOR, storage, node); + release(); } /** @@ -275,10 +311,12 @@ public: * @param other The instance to copy from. * @return This meta any object. */ - meta_any & operator=(const meta_any &other) { - std::exchange(vtable, other.vtable)(operation::DTOR, storage, node); + meta_any &operator=(const meta_any &other) { + release(); storage = other.storage; + ctx = other.ctx; node = other.node; + vtable = other.vtable; return *this; } @@ -287,23 +325,12 @@ public: * @param other The instance to move from. * @return This meta any object. */ - meta_any & operator=(meta_any &&other) ENTT_NOEXCEPT { - std::exchange(vtable, std::exchange(other.vtable, &basic_vtable))(operation::DTOR, storage, node); + meta_any &operator=(meta_any &&other) noexcept { + release(); storage = std::move(other.storage); - node = std::exchange(other.node, nullptr); - return *this; - } - - /** - * @brief Value assignment operator. - * @tparam Type Type of object to use to initialize the wrapper. - * @param value An instance of an object to use to initialize the wrapper. - * @return This meta any object. - */ - template - [[deprecated("Use std::in_place_type, entt::make_meta, emplace or forward_as_meta instead")]] - meta_any & operator=(std::reference_wrapper value) { - emplace(value.get()); + ctx = other.ctx; + node = std::exchange(other.node, internal::meta_type_node{}); + vtable = std::exchange(other.vtable, &basic_vtable); return *this; } @@ -320,48 +347,35 @@ public: return *this; } - /** - * @brief Returns the type of the underlying object. - * @return The type of the underlying object, if any. - */ - [[nodiscard]] inline meta_type type() const ENTT_NOEXCEPT; + /*! @copydoc any::type */ + [[nodiscard]] inline meta_type type() const noexcept; - /** - * @brief Returns an opaque pointer to the contained instance. - * @return An opaque pointer the contained instance, if any. - */ - [[nodiscard]] const void * data() const ENTT_NOEXCEPT { + /*! @copydoc any::data */ + [[nodiscard]] const void *data() const noexcept { return storage.data(); } - /*! @copydoc data */ - [[nodiscard]] void * data() ENTT_NOEXCEPT { + /*! @copydoc any::data */ + [[nodiscard]] void *data() noexcept { return storage.data(); } /** * @brief Invokes the underlying function, if possible. - * - * @sa meta_func::invoke - * * @tparam Args Types of arguments to use to invoke the function. * @param id Unique identifier. * @param args Parameters to use to invoke the function. * @return A wrapper containing the returned value, if any. */ template - meta_any invoke(const id_type id, Args &&... args) const; + meta_any invoke(const id_type id, Args &&...args) const; /*! @copydoc invoke */ template - meta_any invoke(const id_type id, Args &&... args); + meta_any invoke(const id_type id, Args &&...args); /** * @brief Sets the value of a given variable. - * - * The type of the value must be such that a cast or conversion to the type - * of the variable is possible. Otherwise, invoking the setter does nothing. - * * @tparam Type Type of value to assign. * @param id Unique identifier. * @param value Parameter to use to set the underlying variable. @@ -386,46 +400,34 @@ public: * @return A (possibly null) pointer to the contained instance. */ template - [[nodiscard]] const Type * try_cast() const { - if(node) { - if(const auto info = type_id(); node->info == info) { - return any_cast(&storage); - } else if(const auto *base = internal::meta_visit<&internal::meta_type_node::base>([info](const auto *curr) { return curr->type()->info == info; }, node); base) { - return static_cast(base->cast(storage.data())); - } - } - - return nullptr; + [[nodiscard]] const Type *try_cast() const { + const auto other = internal::resolve>(internal::meta_context::from(*ctx)); + return static_cast(internal::try_cast(internal::meta_context::from(*ctx), node, other, data())); } /*! @copydoc try_cast */ template - [[nodiscard]] Type * try_cast() { - if(node) { - if(const auto info = type_id(); node->info == info) { - return any_cast(&storage); - } else if(const auto *base = internal::meta_visit<&internal::meta_type_node::base>([info](const auto *curr) { return curr->type()->info == info; }, node); base) { - return static_cast(const_cast *>(base->cast(static_cast &>(storage).data()))); - } + [[nodiscard]] Type *try_cast() { + if constexpr(std::is_const_v) { + return std::as_const(*this).try_cast>(); + } else { + const auto other = internal::resolve>(internal::meta_context::from(*ctx)); + return static_cast(const_cast(internal::try_cast(internal::meta_context::from(*ctx), node, other, data()))); } - - return nullptr; } /** * @brief Tries to cast an instance to a given type. * - * The type of the instance must be such that the cast is possible. - * * @warning - * Attempting to perform an invalid cast results in undefined behavior. + * Attempting to perform an invalid cast results is undefined behavior. * * @tparam Type Type to which to cast the instance. * @return A reference to the contained instance. */ template [[nodiscard]] Type cast() const { - auto * const instance = try_cast>(); + auto *const instance = try_cast>(); ENTT_ASSERT(instance, "Invalid instance"); return static_cast(*instance); } @@ -434,11 +436,36 @@ public: template [[nodiscard]] Type cast() { // forces const on non-reference types to make them work also with wrappers for const references - auto * const instance = try_cast>(); + auto *const instance = try_cast>(); ENTT_ASSERT(instance, "Invalid instance"); return static_cast(*instance); } + /** + * @brief Converts an object in such a way that a given cast becomes viable. + * @param type Meta type to which the cast is requested. + * @return A valid meta any object if there exists a viable conversion, an + * invalid one otherwise. + */ + [[nodiscard]] meta_any allow_cast(const meta_type &type) const; + + /** + * @brief Converts an object in such a way that a given cast becomes viable. + * @param type Meta type to which the cast is requested. + * @return True if there exists a viable conversion, false otherwise. + */ + [[nodiscard]] bool allow_cast(const meta_type &type) { + if(auto other = std::as_const(*this).allow_cast(type); other) { + if(other.owner()) { + std::swap(*this, other); + } + + return true; + } + + return false; + } + /** * @brief Converts an object in such a way that a given cast becomes viable. * @tparam Type Type to which the cast is requested. @@ -447,15 +474,12 @@ public: */ template [[nodiscard]] meta_any allow_cast() const { - if(try_cast>() != nullptr) { - return as_ref(); - } else if(node) { - if(const auto * const conv = internal::meta_visit<&internal::meta_type_node::conv>([info = type_id()](const auto *curr) { return curr->type()->info == info; }, node); conv) { - return conv->conv(storage.data()); - } + if constexpr(std::is_reference_v && !std::is_const_v>) { + return meta_any{meta_ctx_arg, *ctx}; + } else { + auto other = internal::resolve>>(internal::meta_context::from(*ctx)); + return allow_cast(meta_type{*ctx, other}); } - - return {}; } /** @@ -465,53 +489,49 @@ public: */ template bool allow_cast() { - // forces const on non-reference types to make them work also with wrappers for const references - if(try_cast>() != nullptr) { - return true; - } else if(node) { - if(const auto * const conv = internal::meta_visit<&internal::meta_type_node::conv>([info = type_id()](const auto *curr) { return curr->type()->info == info; }, node); conv) { - *this = conv->conv(std::as_const(storage).data()); - return true; - } - } - - return false; + auto other = internal::resolve>>(internal::meta_context::from(*ctx)); + return allow_cast(meta_type{*ctx, other}) && (!(std::is_reference_v && !std::is_const_v>) || storage.data() != nullptr); } - /** - * @brief Replaces the contained object by creating a new instance directly. - * @tparam Type Type of object to use to initialize the wrapper. - * @tparam Args Types of arguments to use to construct the new instance. - * @param args Parameters to use to construct the instance. - */ + /*! @copydoc any::emplace */ template - void emplace(Args &&... args) { - std::exchange(vtable, &basic_vtable>>)(operation::DTOR, storage, node); + void emplace(Args &&...args) { + release(); storage.emplace(std::forward(args)...); - node = internal::meta_info::resolve(); + node = internal::resolve>>(internal::meta_context::from(*ctx)); + vtable = &basic_vtable>>; } - /*! @brief Destroys contained object */ + /*! @copydoc any::assign */ + bool assign(const meta_any &other); + + /*! @copydoc any::assign */ + bool assign(meta_any &&other); + + /*! @copydoc any::reset */ void reset() { - std::exchange(vtable, &basic_vtable)(operation::DTOR, storage, node); + release(); storage.reset(); - node = nullptr; + node = {}; + vtable = &basic_vtable; } /** * @brief Returns a sequence container proxy. * @return A sequence container proxy for the underlying object. */ - [[nodiscard]] meta_sequence_container as_sequence_container() ENTT_NOEXCEPT { - meta_sequence_container proxy; - vtable(operation::SEQ, storage.as_ref(), &proxy); + [[nodiscard]] meta_sequence_container as_sequence_container() noexcept { + any detached = storage.as_ref(); + meta_sequence_container proxy{*ctx}; + vtable(operation::seq, detached, &proxy); return proxy; } /*! @copydoc as_sequence_container */ - [[nodiscard]] meta_sequence_container as_sequence_container() const ENTT_NOEXCEPT { - meta_sequence_container proxy; - vtable(operation::SEQ, storage.as_ref(), &proxy); + [[nodiscard]] meta_sequence_container as_sequence_container() const noexcept { + any detached = storage.as_ref(); + meta_sequence_container proxy{*ctx}; + vtable(operation::seq, detached, &proxy); return proxy; } @@ -519,16 +539,18 @@ public: * @brief Returns an associative container proxy. * @return An associative container proxy for the underlying object. */ - [[nodiscard]] meta_associative_container as_associative_container() ENTT_NOEXCEPT { - meta_associative_container proxy; - vtable(operation::ASSOC, storage.as_ref(), &proxy); + [[nodiscard]] meta_associative_container as_associative_container() noexcept { + any detached = storage.as_ref(); + meta_associative_container proxy{*ctx}; + vtable(operation::assoc, detached, &proxy); return proxy; } /*! @copydoc as_associative_container */ - [[nodiscard]] meta_associative_container as_associative_container() const ENTT_NOEXCEPT { - meta_associative_container proxy; - vtable(operation::ASSOC, storage.as_ref(), &proxy); + [[nodiscard]] meta_associative_container as_associative_container() const noexcept { + any detached = storage.as_ref(); + meta_associative_container proxy{*ctx}; + vtable(operation::assoc, detached, &proxy); return proxy; } @@ -537,9 +559,9 @@ public: * @return A wrapper that shares a reference to an unmanaged object if the * wrapped element is dereferenceable, an invalid meta any otherwise. */ - [[nodiscard]] meta_any operator*() const ENTT_NOEXCEPT { - meta_any ret{}; - vtable(operation::DEREF, storage, &ret); + [[nodiscard]] meta_any operator*() const noexcept { + meta_any ret{meta_ctx_arg, *ctx}; + vtable(operation::deref, storage, &ret); return ret; } @@ -547,63 +569,54 @@ public: * @brief Returns false if a wrapper is invalid, true otherwise. * @return False if the wrapper is invalid, true otherwise. */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { - return !(node == nullptr); + [[nodiscard]] explicit operator bool() const noexcept { + return !(node.info == nullptr); } - /** - * @brief Checks if two wrappers differ in their content. - * @param other Wrapper with which to compare. - * @return False if the two objects differ in their content, true otherwise. - */ - [[nodiscard]] bool operator==(const meta_any &other) const { - return (!node && !other.node) || (node && other.node && node->info == other.node->info && storage == other.storage); + /*! @copydoc any::operator== */ + [[nodiscard]] bool operator==(const meta_any &other) const noexcept { + return (ctx == other.ctx) && ((!node.info && !other.node.info) || (node.info && other.node.info && *node.info == *other.node.info && storage == other.storage)); } - /** - * @brief Aliasing constructor. - * @return A wrapper that shares a reference to an unmanaged object. - */ - [[nodiscard]] meta_any as_ref() ENTT_NOEXCEPT { - return meta_any{*this, storage.as_ref()}; + /*! @copydoc any::operator!= */ + [[nodiscard]] bool operator!=(const meta_any &other) const noexcept { + return !(*this == other); } - /*! @copydoc as_ref */ - [[nodiscard]] meta_any as_ref() const ENTT_NOEXCEPT { - return meta_any{*this, storage.as_ref()}; + /*! @copydoc any::as_ref */ + [[nodiscard]] meta_any as_ref() noexcept { + return meta_any{*ctx, *this, storage.as_ref()}; + } + + /*! @copydoc any::as_ref */ + [[nodiscard]] meta_any as_ref() const noexcept { + return meta_any{*ctx, *this, storage.as_ref()}; + } + + /*! @copydoc any::owner */ + [[nodiscard]] bool owner() const noexcept { + return storage.owner(); } private: any storage; - internal::meta_type_node *node; + const meta_ctx *ctx; + internal::meta_type_node node; vtable_type *vtable; }; - /** - * @brief Checks if two wrappers differ in their content. - * @param lhs A wrapper, either empty or not. - * @param rhs A wrapper, either empty or not. - * @return True if the two wrappers differ in their content, false otherwise. + * @brief Forwards its argument and avoids copies for lvalue references. + * @tparam Type Type of argument to use to construct the new instance. + * @param value Parameter to use to construct the instance. + * @param ctx The context from which to search for meta types. + * @return A properly initialized and not necessarily owning wrapper. */ -[[nodiscard]] inline bool operator!=(const meta_any &lhs, const meta_any &rhs) ENTT_NOEXCEPT { - return !(lhs == rhs); +template +meta_any forward_as_meta(const meta_ctx &ctx, Type &&value) { + return meta_any{ctx, std::in_place_type, std::forward(value)}; } - -/** - * @brief Constructs a wrapper from a given type, passing it all arguments. - * @tparam Type Type of object to use to initialize the wrapper. - * @tparam Args Types of arguments to use to construct the new instance. - * @param args Parameters to use to construct the instance. - * @return A properly initialized wrapper for an object of the given type. - */ -template -meta_any make_meta(Args &&... args) { - return meta_any{std::in_place_type, std::forward(args)...}; -} - - /** * @brief Forwards its argument and avoids copies for lvalue references. * @tparam Type Type of argument to use to construct the new instance. @@ -612,10 +625,9 @@ meta_any make_meta(Args &&... args) { */ template meta_any forward_as_meta(Type &&value) { - return meta_any{std::in_place_type, std::decay_t, Type>>, std::forward(value)}; + return forward_as_meta(locator::value_or(), std::forward(value)); } - /** * @brief Opaque pointers to instances of any type. * @@ -624,9 +636,65 @@ meta_any forward_as_meta(Type &&value) { * Handles are used to generate references to actual objects when needed. */ struct meta_handle { - /*! @brief Default constructor. */ - meta_handle() = default; + /*! Default constructor. */ + meta_handle() noexcept + : meta_handle{meta_ctx_arg, locator::value_or()} {} + /** + * @brief Context aware constructor. + * @param area The context from which to search for meta types. + */ + meta_handle(meta_ctx_arg_t, const meta_ctx &area) noexcept + : any{meta_ctx_arg, area} {} + + /** + * @brief Creates a handle that points to an unmanaged object. + * @param value An instance of an object to use to initialize the handle. + */ + meta_handle(meta_any &value) noexcept + : any{value.as_ref()} {} + + /** + * @brief Creates a handle that points to an unmanaged object. + * @param value An instance of an object to use to initialize the handle. + */ + meta_handle(const meta_any &value) noexcept + : any{value.as_ref()} {} + + /** + * @brief Creates a handle that points to an unmanaged object. + * @tparam Type Type of object to use to initialize the handle. + * @param ctx The context from which to search for meta types. + * @param value An instance of an object to use to initialize the handle. + */ + template, meta_handle>>> + meta_handle(const meta_ctx &ctx, Type &value) noexcept + : any{ctx, std::in_place_type, value} {} + + /** + * @brief Creates a handle that points to an unmanaged object. + * @tparam Type Type of object to use to initialize the handle. + * @param value An instance of an object to use to initialize the handle. + */ + template, meta_handle>>> + meta_handle(Type &value) noexcept + : meta_handle{locator::value_or(), value} {} + + /** + * @brief Context aware copy constructor. + * @param area The context from which to search for meta types. + * @param other The instance to copy from. + */ + meta_handle(const meta_ctx &area, const meta_handle &other) + : any{area, other.any} {} + + /** + * @brief Context aware move constructor. + * @param area The context from which to search for meta types. + * @param other The instance to move from. + */ + meta_handle(const meta_ctx &area, meta_handle &&other) + : any{area, std::move(other.any)} {} /*! @brief Default copy constructor, deleted on purpose. */ meta_handle(const meta_handle &) = delete; @@ -638,35 +706,19 @@ struct meta_handle { * @brief Default copy assignment operator, deleted on purpose. * @return This meta handle. */ - meta_handle & operator=(const meta_handle &) = delete; + meta_handle &operator=(const meta_handle &) = delete; /** * @brief Default move assignment operator. * @return This meta handle. */ - meta_handle & operator=(meta_handle &&) = default; - - /** - * @brief Creates a handle that points to an unmanaged object. - * @tparam Type Type of object to use to initialize the handle. - * @param value An instance of an object to use to initialize the handle. - */ - template, meta_handle>>> - meta_handle(Type &value) ENTT_NOEXCEPT - : meta_handle{} - { - if constexpr(std::is_same_v, meta_any>) { - any = value.as_ref(); - } else { - any.emplace(value); - } - } + meta_handle &operator=(meta_handle &&) = default; /** * @brief Returns false if a handle is invalid, true otherwise. * @return False if the handle is invalid, true otherwise. */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { + [[nodiscard]] explicit operator bool() const noexcept { return static_cast(any); } @@ -674,12 +726,12 @@ struct meta_handle { * @brief Access operator for accessing the contained opaque object. * @return A wrapper that shares a reference to an unmanaged object. */ - [[nodiscard]] meta_any * operator->() { + [[nodiscard]] meta_any *operator->() { return &any; } /*! @copydoc operator-> */ - [[nodiscard]] const meta_any * operator->() const { + [[nodiscard]] const meta_any *operator->() const { return &any; } @@ -687,187 +739,91 @@ private: meta_any any; }; - /*! @brief Opaque wrapper for properties of any type. */ struct meta_prop { - /*! @brief Node type. */ - using node_type = internal::meta_prop_node; + /*! @brief Default constructor. */ + meta_prop() noexcept + : node{}, + ctx{} {} /** - * @brief Constructs an instance from a given node. + * @brief Context aware constructor for meta objects. + * @param area The context from which to search for meta types. * @param curr The underlying node with which to construct the instance. */ - meta_prop(const node_type *curr = nullptr) ENTT_NOEXCEPT - : node{curr} - {} - - /** - * @brief Returns the stored key as a const reference. - * @return A wrapper containing the key stored with the property. - */ - [[nodiscard]] meta_any key() const { - return node->id.as_ref(); - } + meta_prop(const meta_ctx &area, const internal::meta_prop_node &curr) noexcept + : node{&curr}, + ctx{&area} {} /** * @brief Returns the stored value by copy. * @return A wrapper containing the value stored with the property. */ [[nodiscard]] meta_any value() const { - return node->value; + return node->value ? node->type(internal::meta_context::from(*ctx)).from_void(*ctx, nullptr, node->value.get()) : meta_any{meta_ctx_arg, *ctx}; } /** * @brief Returns true if an object is valid, false otherwise. * @return True if the object is valid, false otherwise. */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { - return !(node == nullptr); + [[nodiscard]] explicit operator bool() const noexcept { + return (node != nullptr); } private: - const node_type *node; + const internal::meta_prop_node *node; + const meta_ctx *ctx; }; - -/*! @brief Opaque wrapper for constructors. */ -struct meta_ctor { - /*! @brief Node type. */ - using node_type = internal::meta_ctor_node; - /*! @brief Unsigned integer type. */ - using size_type = typename node_type::size_type; - - /*! @copydoc meta_prop::meta_prop */ - meta_ctor(const node_type *curr = nullptr) ENTT_NOEXCEPT - : node{curr} - {} - - /** - * @brief Returns the type to which an object belongs. - * @return The type to which the object belongs. - */ - [[nodiscard]] inline meta_type parent() const ENTT_NOEXCEPT; - - /** - * @brief Returns the number of arguments accepted by a constructor. - * @return The number of arguments accepted by the constructor. - */ - [[nodiscard]] size_type arity() const ENTT_NOEXCEPT { - return node->arity; - } - - /** - * @brief Returns the type of the i-th argument of a constructor. - * @param index Index of the argument of which to return the type. - * @return The type of the i-th argument of a constructor. - */ - [[nodiscard]] meta_type arg(size_type index) const ENTT_NOEXCEPT; - - /** - * @brief Creates an instance of the underlying type, if possible. - * - * Parameters must be such that a cast or conversion to the required types - * is possible. Otherwise, an empty and thus invalid wrapper is returned. - * - * @param args Parameters to use to construct the instance. - * @param sz Number of parameters to use to construct the instance. - * @return A wrapper containing the new instance, if any. - */ - [[nodiscard]] meta_any invoke(meta_any * const args, const size_type sz) const { - return sz == arity() ? node->invoke(args) : meta_any{}; - } - - /** - * @copybrief invoke - * - * @sa invoke - * - * @tparam Args Types of arguments to use to construct the instance. - * @param args Parameters to use to construct the instance. - * @return A wrapper containing the new instance, if any. - */ - template - [[nodiscard]] meta_any invoke([[maybe_unused]] Args &&... args) const { - meta_any arguments[sizeof...(Args) + 1u]{std::forward(args)...}; - return invoke(arguments, sizeof...(Args)); - } - - /** - * @brief Returns a range to use to visit all properties. - * @return An iterable range to use to visit all properties. - */ - [[nodiscard]] meta_range prop() const ENTT_NOEXCEPT { - return node->prop; - } - - /** - * @brief Returns the property associated with a given key. - * @param key The key to use to search for a property. - * @return The property associated with the given key, if any. - */ - [[nodiscard]] meta_prop prop(meta_any key) const { - return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return curr->id == key; }, node); - } - - /** - * @brief Returns true if an object is valid, false otherwise. - * @return True if the object is valid, false otherwise. - */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { - return !(node == nullptr); - } - -private: - const node_type *node; -}; - - /*! @brief Opaque wrapper for data members. */ struct meta_data { - /*! @brief Node type. */ - using node_type = internal::meta_data_node; + /*! @brief Unsigned integer type. */ + using size_type = typename internal::meta_data_node::size_type; - /*! @copydoc meta_prop::meta_prop */ - meta_data(const node_type *curr = nullptr) ENTT_NOEXCEPT - : node{curr} - {} + /*! @brief Default constructor. */ + meta_data() noexcept + : node{}, + ctx{} {} - /*! @copydoc meta_type::id */ - [[nodiscard]] id_type id() const ENTT_NOEXCEPT { - return node->id; + /** + * @brief Context aware constructor for meta objects. + * @param area The context from which to search for meta types. + * @param curr The underlying node with which to construct the instance. + */ + meta_data(const meta_ctx &area, const internal::meta_data_node &curr) noexcept + : node{&curr}, + ctx{&area} {} + + /** + * @brief Returns the number of setters available. + * @return The number of setters available. + */ + [[nodiscard]] size_type arity() const noexcept { + return node->arity; } - /*! @copydoc meta_ctor::parent */ - [[nodiscard]] inline meta_type parent() const ENTT_NOEXCEPT; - /** * @brief Indicates whether a data member is constant or not. * @return True if the data member is constant, false otherwise. */ - [[nodiscard]] bool is_const() const ENTT_NOEXCEPT { - return node->is_const; + [[nodiscard]] bool is_const() const noexcept { + return static_cast(node->traits & internal::meta_traits::is_const); } /** * @brief Indicates whether a data member is static or not. * @return True if the data member is static, false otherwise. */ - [[nodiscard]] bool is_static() const ENTT_NOEXCEPT { - return node->is_static; + [[nodiscard]] bool is_static() const noexcept { + return static_cast(node->traits & internal::meta_traits::is_static); } /*! @copydoc meta_any::type */ - [[nodiscard]] inline meta_type type() const ENTT_NOEXCEPT; + [[nodiscard]] inline meta_type type() const noexcept; /** * @brief Sets the value of a given variable. - * - * It must be possible to cast the instance to the parent type of the data - * member. Otherwise, invoking the setter results in an undefined - * behavior.
- * The type of the value must be such that a cast or conversion to the type - * of the variable is possible. Otherwise, invoking the setter does nothing. - * * @tparam Type Type of value to assign. * @param instance An opaque instance of the underlying type. * @param value Parameter to use to set the underlying variable. @@ -875,74 +831,80 @@ struct meta_data { */ template bool set(meta_handle instance, Type &&value) const { - return node->set && node->set(std::move(instance), std::forward(value)); + return node->set && node->set(meta_handle{*ctx, std::move(instance)}, meta_any{*ctx, std::forward(value)}); } /** * @brief Gets the value of a given variable. - * - * It must be possible to cast the instance to the parent type of the data - * member. Otherwise, invoking the getter results in an undefined behavior. - * * @param instance An opaque instance of the underlying type. * @return A wrapper containing the value of the underlying variable. */ [[nodiscard]] meta_any get(meta_handle instance) const { - return node->get(std::move(instance)); - } - - /*! @copydoc meta_ctor::prop */ - [[nodiscard]] meta_range prop() const ENTT_NOEXCEPT { - return node->prop; + return node->get(*ctx, meta_handle{*ctx, std::move(instance)}); } /** - * @brief Returns the property associated with a given key. - * @param key The key to use to search for a property. - * @return The property associated with the given key, if any. + * @brief Returns the type accepted by the i-th setter. + * @param index Index of the setter of which to return the accepted type. + * @return The type accepted by the i-th setter. */ - [[nodiscard]] meta_prop prop(meta_any key) const { - return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return curr->id == key; }, node); + [[nodiscard]] inline meta_type arg(const size_type index) const noexcept; + + /** + * @brief Returns a range to visit registered meta properties. + * @return An iterable range to visit registered meta properties. + */ + [[nodiscard]] meta_range prop() const noexcept { + return {{*ctx, node->prop.cbegin()}, {*ctx, node->prop.cend()}}; + } + + /** + * @brief Lookup utility for meta properties. + * @param key The key to use to search for a property. + * @return The registered meta property for the given key, if any. + */ + [[nodiscard]] meta_prop prop(const id_type key) const { + const auto it = node->prop.find(key); + return it != node->prop.cend() ? meta_prop{*ctx, it->second} : meta_prop{}; } /** * @brief Returns true if an object is valid, false otherwise. * @return True if the object is valid, false otherwise. */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { - return !(node == nullptr); + [[nodiscard]] explicit operator bool() const noexcept { + return (node != nullptr); } private: - const node_type *node; + const internal::meta_data_node *node; + const meta_ctx *ctx; }; - /*! @brief Opaque wrapper for member functions. */ struct meta_func { - /*! @brief Node type. */ - using node_type = internal::meta_func_node; /*! @brief Unsigned integer type. */ - using size_type = typename node_type::size_type; + using size_type = typename internal::meta_func_node::size_type; - /*! @copydoc meta_prop::meta_prop */ - meta_func(const node_type *curr = nullptr) ENTT_NOEXCEPT - : node{curr} - {} + /*! @brief Default constructor. */ + meta_func() noexcept + : node{}, + ctx{} {} - /*! @copydoc meta_type::id */ - [[nodiscard]] id_type id() const ENTT_NOEXCEPT { - return node->id; - } - - /*! @copydoc meta_ctor::parent */ - [[nodiscard]] inline meta_type parent() const ENTT_NOEXCEPT; + /** + * @brief Context aware constructor for meta objects. + * @param area The context from which to search for meta types. + * @param curr The underlying node with which to construct the instance. + */ + meta_func(const meta_ctx &area, const internal::meta_func_node &curr) noexcept + : node{&curr}, + ctx{&area} {} /** * @brief Returns the number of arguments accepted by a member function. * @return The number of arguments accepted by the member function. */ - [[nodiscard]] size_type arity() const ENTT_NOEXCEPT { + [[nodiscard]] size_type arity() const noexcept { return node->arity; } @@ -950,270 +912,263 @@ struct meta_func { * @brief Indicates whether a member function is constant or not. * @return True if the member function is constant, false otherwise. */ - [[nodiscard]] bool is_const() const ENTT_NOEXCEPT { - return node->is_const; + [[nodiscard]] bool is_const() const noexcept { + return static_cast(node->traits & internal::meta_traits::is_const); } /** * @brief Indicates whether a member function is static or not. * @return True if the member function is static, false otherwise. */ - [[nodiscard]] bool is_static() const ENTT_NOEXCEPT { - return node->is_static; + [[nodiscard]] bool is_static() const noexcept { + return static_cast(node->traits & internal::meta_traits::is_static); } /** * @brief Returns the return type of a member function. * @return The return type of the member function. */ - [[nodiscard]] inline meta_type ret() const ENTT_NOEXCEPT; + [[nodiscard]] inline meta_type ret() const noexcept; /** * @brief Returns the type of the i-th argument of a member function. * @param index Index of the argument of which to return the type. * @return The type of the i-th argument of a member function. */ - [[nodiscard]] inline meta_type arg(size_type index) const ENTT_NOEXCEPT; + [[nodiscard]] inline meta_type arg(const size_type index) const noexcept; /** * @brief Invokes the underlying function, if possible. * - * To invoke a member function, the parameters must be such that a cast or - * conversion to the required types is possible. Otherwise, an empty and - * thus invalid wrapper is returned.
- * It must be possible to cast the instance to the parent type of the member - * function. Otherwise, invoking the underlying function results in an - * undefined behavior. + * @warning + * The context of the arguments is **not** changed.
+ * It's up to the caller to bind them to the right context(s). * * @param instance An opaque instance of the underlying type. * @param args Parameters to use to invoke the function. * @param sz Number of parameters to use to invoke the function. * @return A wrapper containing the returned value, if any. */ - meta_any invoke(meta_handle instance, meta_any * const args, const size_type sz) const { - return sz == arity() ? node->invoke(std::move(instance), args) : meta_any{}; + meta_any invoke(meta_handle instance, meta_any *const args, const size_type sz) const { + return sz == arity() ? node->invoke(*ctx, meta_handle{*ctx, std::move(instance)}, args) : meta_any{meta_ctx_arg, *ctx}; } /** * @copybrief invoke - * - * @sa invoke - * * @tparam Args Types of arguments to use to invoke the function. * @param instance An opaque instance of the underlying type. * @param args Parameters to use to invoke the function. - * @return A wrapper containing the new instance, if any. + * @return A wrapper containing the returned value, if any. */ template - meta_any invoke(meta_handle instance, Args &&... args) const { - meta_any arguments[sizeof...(Args) + 1u]{std::forward(args)...}; - return invoke(std::move(instance), arguments, sizeof...(Args)); + meta_any invoke(meta_handle instance, Args &&...args) const { + meta_any arguments[sizeof...(Args) + 1u]{{*ctx, std::forward(args)}...}; + return invoke(meta_handle{*ctx, std::move(instance)}, arguments, sizeof...(Args)); } - /*! @copydoc meta_ctor::prop */ - [[nodiscard]] meta_range prop() const ENTT_NOEXCEPT { - return node->prop; + /*! @copydoc meta_data::prop */ + [[nodiscard]] meta_range prop() const noexcept { + return {{*ctx, node->prop.cbegin()}, {*ctx, node->prop.cend()}}; } /** - * @brief Returns the property associated with a given key. + * @brief Lookup utility for meta properties. * @param key The key to use to search for a property. - * @return The property associated with the given key, if any. + * @return The registered meta property for the given key, if any. */ - [[nodiscard]] meta_prop prop(meta_any key) const { - return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return curr->id == key; }, node); + [[nodiscard]] meta_prop prop(const id_type key) const { + const auto it = node->prop.find(key); + return it != node->prop.cend() ? meta_prop{*ctx, it->second} : meta_prop{}; + } + + /** + * @brief Returns the next overload of a given function, if any. + * @return The next overload of the given function, if any. + */ + [[nodiscard]] meta_func next() const { + return node->next ? meta_func{*ctx, *node->next} : meta_func{}; } /** * @brief Returns true if an object is valid, false otherwise. * @return True if the object is valid, false otherwise. */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { - return !(node == nullptr); + [[nodiscard]] explicit operator bool() const noexcept { + return (node != nullptr); } private: - const node_type *node; + const internal::meta_func_node *node; + const meta_ctx *ctx; }; - /*! @brief Opaque wrapper for types. */ class meta_type { - static bool can_cast_or_convert(const internal::meta_type_node *type, const type_info info) ENTT_NOEXCEPT { - if(type->info == info) { - return true; - } + template + [[nodiscard]] auto lookup(meta_any *const args, const typename internal::meta_type_node::size_type sz, [[maybe_unused]] bool constness, Func next) const { + decltype(next()) candidate = nullptr; + size_type same{}; + bool ambiguous{}; - for(const auto *curr = type->conv; curr; curr = curr->next) { - if(curr->type()->info == info) { - return true; + for(auto curr = next(); curr; curr = next()) { + if constexpr(std::is_same_v, internal::meta_func_node>) { + if(constness && !static_cast(curr->traits & internal::meta_traits::is_const)) { + continue; + } + } + + if(curr->arity == sz) { + size_type match{}; + size_type pos{}; + + for(; pos < sz && args[pos]; ++pos) { + const auto other = curr->arg(*ctx, pos); + const auto type = args[pos].type(); + + if(const auto &info = other.info(); info == type.info()) { + ++match; + } else if(!((type.node.details && (type.node.details->base.contains(info.hash()) || type.node.details->conv.contains(info.hash()))) || (type.node.conversion_helper && other.node.conversion_helper))) { + break; + } + } + + if(pos == sz) { + if(!candidate || match > same) { + candidate = curr; + same = match; + ambiguous = false; + } else if(match == same) { + if constexpr(std::is_same_v, internal::meta_func_node>) { + if(static_cast(curr->traits & internal::meta_traits::is_const) != static_cast(candidate->traits & internal::meta_traits::is_const)) { + candidate = static_cast(candidate->traits & internal::meta_traits::is_const) ? curr : candidate; + ambiguous = false; + continue; + } + } + + ambiguous = true; + } + } } } - for(const auto *curr = type->base; curr; curr = curr->next) { - if(auto *target = curr->type(); can_cast_or_convert(target, info)) { - return true; - } - } - - return false; - } - - template - [[nodiscard]] static const internal::meta_ctor_node * ctor(const internal::meta_ctor_node *curr, std::index_sequence) { - for(; curr; curr = curr->next) { - if(curr->arity == sizeof...(Args) && (can_cast_or_convert(internal::meta_info::resolve(), curr->arg(Index).info()) && ...)) { - return curr; - } - } - - return nullptr; - } - - template - void unregister_all(Node **curr) { - while(*curr) { - (unregister_all(&((*curr)->*Member)), ...); - *curr = std::exchange((*curr)->next, nullptr); - } + return ambiguous ? nullptr : candidate; } public: - /*! @brief Node type. */ - using node_type = internal::meta_type_node; - /*! @brief Node type. */ - using base_node_type = internal::meta_base_node; /*! @brief Unsigned integer type. */ - using size_type = typename node_type::size_type; + using size_type = typename internal::meta_type_node::size_type; - /*! @copydoc meta_prop::meta_prop */ - meta_type(node_type *curr = nullptr) ENTT_NOEXCEPT - : node{curr} - {} + /*! @brief Default constructor. */ + meta_type() noexcept + : node{}, + ctx{} {} /** - * @brief Constructs an instance from a given base node. - * @param curr The base node with which to construct the instance. + * @brief Context aware constructor for meta objects. + * @param area The context from which to search for meta types. + * @param curr The underlying node with which to construct the instance. */ - meta_type(base_node_type *curr) ENTT_NOEXCEPT - : node{curr ? curr->type() : nullptr} - {} + meta_type(const meta_ctx &area, const internal::meta_type_node &curr) noexcept + : node{curr}, + ctx{&area} {} + + /** + * @brief Context aware constructor for meta objects. + * @param area The context from which to search for meta types. + * @param curr The underlying node with which to construct the instance. + */ + meta_type(const meta_ctx &area, const internal::meta_base_node &curr) noexcept + : meta_type{area, curr.type(internal::meta_context::from(area))} {} /** * @brief Returns the type info object of the underlying type. * @return The type info object of the underlying type. */ - [[nodiscard]] type_info info() const ENTT_NOEXCEPT { - return node->info; + [[nodiscard]] const type_info &info() const noexcept { + return *node.info; } /** * @brief Returns the identifier assigned to a type. * @return The identifier assigned to the type. */ - [[nodiscard]] id_type id() const ENTT_NOEXCEPT { - return node->id; + [[nodiscard]] id_type id() const noexcept { + return node.id; } /** * @brief Returns the size of the underlying type if known. * @return The size of the underlying type if known, 0 otherwise. */ - [[nodiscard]] size_type size_of() const ENTT_NOEXCEPT { - return node->size_of; + [[nodiscard]] size_type size_of() const noexcept { + return node.size_of; } /** - * @brief Checks whether a type refers to void or not. - * @return True if the underlying type is void, false otherwise. + * @brief Checks whether a type refers to an arithmetic type or not. + * @return True if the underlying type is an arithmetic type, false + * otherwise. */ - [[nodiscard]] bool is_void() const ENTT_NOEXCEPT { - return node->is_void; + [[nodiscard]] bool is_arithmetic() const noexcept { + return static_cast(node.traits & internal::meta_traits::is_arithmetic); } /** * @brief Checks whether a type refers to an integral type or not. * @return True if the underlying type is an integral type, false otherwise. */ - [[nodiscard]] bool is_integral() const ENTT_NOEXCEPT { - return node->is_integral; + [[nodiscard]] bool is_integral() const noexcept { + return static_cast(node.traits & internal::meta_traits::is_integral); } /** - * @brief Checks whether a type refers to a floating-point type or not. - * @return True if the underlying type is a floating-point type, false - * otherwise. + * @brief Checks whether a type refers to a signed type or not. + * @return True if the underlying type is a signed type, false otherwise. */ - [[nodiscard]] bool is_floating_point() const ENTT_NOEXCEPT { - return node->is_floating_point; + [[nodiscard]] bool is_signed() const noexcept { + return static_cast(node.traits & internal::meta_traits::is_signed); } /** * @brief Checks whether a type refers to an array type or not. * @return True if the underlying type is an array type, false otherwise. */ - [[nodiscard]] bool is_array() const ENTT_NOEXCEPT { - return node->is_array; + [[nodiscard]] bool is_array() const noexcept { + return static_cast(node.traits & internal::meta_traits::is_array); } /** * @brief Checks whether a type refers to an enum or not. * @return True if the underlying type is an enum, false otherwise. */ - [[nodiscard]] bool is_enum() const ENTT_NOEXCEPT { - return node->is_enum; - } - - /** - * @brief Checks whether a type refers to an union or not. - * @return True if the underlying type is an union, false otherwise. - */ - [[nodiscard]] bool is_union() const ENTT_NOEXCEPT { - return node->is_union; + [[nodiscard]] bool is_enum() const noexcept { + return static_cast(node.traits & internal::meta_traits::is_enum); } /** * @brief Checks whether a type refers to a class or not. * @return True if the underlying type is a class, false otherwise. */ - [[nodiscard]] bool is_class() const ENTT_NOEXCEPT { - return node->is_class; + [[nodiscard]] bool is_class() const noexcept { + return static_cast(node.traits & internal::meta_traits::is_class); } /** * @brief Checks whether a type refers to a pointer or not. * @return True if the underlying type is a pointer, false otherwise. */ - [[nodiscard]] bool is_pointer() const ENTT_NOEXCEPT { - return node->is_pointer; + [[nodiscard]] bool is_pointer() const noexcept { + return node.info && (node.info->hash() != remove_pointer().info().hash()); } /** - * @brief Checks whether a type refers to a function pointer or not. - * @return True if the underlying type is a function pointer, false - * otherwise. + * @brief Provides the type for which the pointer is defined. + * @return The type for which the pointer is defined or this type if it + * doesn't refer to a pointer type. */ - [[nodiscard]] bool is_function_pointer() const ENTT_NOEXCEPT { - return node->is_function_pointer; - } - - /** - * @brief Checks whether a type refers to a pointer to data member or not. - * @return True if the underlying type is a pointer to data member, false - * otherwise. - */ - [[nodiscard]] bool is_member_object_pointer() const ENTT_NOEXCEPT { - return node->is_member_object_pointer; - } - - /** - * @brief Checks whether a type refers to a pointer to member function or - * not. - * @return True if the underlying type is a pointer to member function, - * false otherwise. - */ - [[nodiscard]] bool is_member_function_pointer() const ENTT_NOEXCEPT { - return node->is_member_function_pointer; + [[nodiscard]] meta_type remove_pointer() const noexcept { + return {*ctx, node.remove_pointer(internal::meta_context::from(*ctx))}; } /** @@ -1221,24 +1176,24 @@ public: * @return True if the underlying type is a pointer-like one, false * otherwise. */ - [[nodiscard]] bool is_pointer_like() const ENTT_NOEXCEPT { - return node->is_pointer_like; + [[nodiscard]] bool is_pointer_like() const noexcept { + return static_cast(node.traits & internal::meta_traits::is_meta_pointer_like); } /** * @brief Checks whether a type refers to a sequence container or not. * @return True if the type is a sequence container, false otherwise. */ - [[nodiscard]] bool is_sequence_container() const ENTT_NOEXCEPT { - return node->is_sequence_container; + [[nodiscard]] bool is_sequence_container() const noexcept { + return static_cast(node.traits & internal::meta_traits::is_meta_sequence_container); } /** * @brief Checks whether a type refers to an associative container or not. * @return True if the type is an associative container, false otherwise. */ - [[nodiscard]] bool is_associative_container() const ENTT_NOEXCEPT { - return node->is_associative_container; + [[nodiscard]] bool is_associative_container() const noexcept { + return static_cast(node.traits & internal::meta_traits::is_meta_associative_container); } /** @@ -1247,27 +1202,24 @@ public: * @return True if the type is a recognized class template specialization, * false otherwise. */ - [[nodiscard]] bool is_template_specialization() const ENTT_NOEXCEPT { - return node->template_info.is_template_specialization; + [[nodiscard]] bool is_template_specialization() const noexcept { + return (node.templ.arity != 0u); } /** - * @brief Returns the number of template arguments, if any. - * @return The number of template arguments, if any. + * @brief Returns the number of template arguments. + * @return The number of template arguments. */ - [[nodiscard]] size_type template_arity() const ENTT_NOEXCEPT { - return node->template_info.arity; + [[nodiscard]] size_type template_arity() const noexcept { + return node.templ.arity; } /** * @brief Returns a tag for the class template of the underlying type. - * - * @sa meta_class_template_tag - * * @return The tag for the class template of the underlying type. */ - [[nodiscard]] inline meta_type template_type() const ENTT_NOEXCEPT { - return is_template_specialization() ? node->template_info.type() : meta_type{}; + [[nodiscard]] inline meta_type template_type() const noexcept { + return node.templ.type ? meta_type{*ctx, node.templ.type(internal::meta_context::from(*ctx))} : meta_type{}; } /** @@ -1275,162 +1227,142 @@ public: * @param index Index of the template argument of which to return the type. * @return The type of the i-th template argument of a type. */ - [[nodiscard]] inline meta_type template_arg(size_type index) const ENTT_NOEXCEPT { - return index < template_arity() ? node->template_info.arg(index) : meta_type{}; + [[nodiscard]] inline meta_type template_arg(const size_type index) const noexcept { + return index < template_arity() ? meta_type{*ctx, node.templ.arg(internal::meta_context::from(*ctx), index)} : meta_type{}; } /** - * @brief Provides the number of dimensions of an array type. - * @return The number of dimensions in case of array types, 0 otherwise. + * @brief Returns a range to visit registered top-level base meta types. + * @return An iterable range to visit registered top-level base meta types. */ - [[nodiscard]] size_type rank() const ENTT_NOEXCEPT { - return node->rank; + [[nodiscard]] meta_range base() const noexcept { + using range_type = meta_range; + return node.details ? range_type{{*ctx, node.details->base.cbegin()}, {*ctx, node.details->base.cend()}} : range_type{}; } /** - * @brief The number of elements along the given dimension of an array type. - * @param dim The dimension of which to return the number of elements. - * @return The number of elements along the given dimension in case of array - * types, 0 otherwise. + * @brief Returns a range to visit registered top-level meta data. + * @return An iterable range to visit registered top-level meta data. */ - [[nodiscard]] size_type extent(size_type dim = {}) const ENTT_NOEXCEPT { - return node->extent(dim); + [[nodiscard]] meta_range data() const noexcept { + using range_type = meta_range; + return node.details ? range_type{{*ctx, node.details->data.cbegin()}, {*ctx, node.details->data.cend()}} : range_type{}; } /** - * @brief Provides the type for which the pointer is defined. - * @return The type for which the pointer is defined or this type if it - * doesn't refer to a pointer type. - */ - [[nodiscard]] meta_type remove_pointer() const ENTT_NOEXCEPT { - return node->remove_pointer(); - } - - /** - * @brief Provides the type for which the array is defined. - * @return The type for which the array is defined or this type if it - * doesn't refer to an array type. - */ - [[nodiscard]] meta_type remove_extent() const ENTT_NOEXCEPT { - return node->remove_extent(); - } - - /** - * @brief Returns a range to use to visit top-level base meta types. - * @return An iterable range to use to visit top-level base meta types. - */ - [[nodiscard]] meta_range base() const ENTT_NOEXCEPT { - return node->base; - } - - /** - * @brief Returns the base meta type associated with a given identifier. + * @brief Lookup utility for meta data (bases are also visited). * @param id Unique identifier. - * @return The base meta type associated with the given identifier, if any. - */ - [[nodiscard]] meta_type base(const id_type id) const { - return internal::meta_visit<&node_type::base>([id](const auto *curr) { return curr->type()->id == id; }, node); - } - - /** - * @brief Returns a range to use to visit top-level constructors. - * @return An iterable range to use to visit top-level constructors. - */ - [[nodiscard]] meta_range ctor() const ENTT_NOEXCEPT { - return node->ctor; - } - - /** - * @brief Returns a constructor for a given list of types of arguments. - * @tparam Args Constructor arguments. - * @return The requested constructor, if any. - */ - template - [[nodiscard]] meta_ctor ctor() const { - return ctor(node->ctor, std::make_index_sequence{}); - } - - /** - * @brief Returns a range to use to visit top-level data. - * @return An iterable range to use to visit top-level data. - */ - [[nodiscard]] meta_range data() const ENTT_NOEXCEPT { - return node->data; - } - - /** - * @brief Returns the data associated with a given identifier. - * - * The data of the base classes will also be visited, if any. - * - * @param id Unique identifier. - * @return The data associated with the given identifier, if any. + * @return The registered meta data for the given identifier, if any. */ [[nodiscard]] meta_data data(const id_type id) const { - return internal::meta_visit<&node_type::data>([id](const auto *curr) { return curr->id == id; }, node); + if(node.details) { + if(const auto it = node.details->data.find(id); it != node.details->data.cend()) { + return meta_data{*ctx, it->second}; + } + } + + for(auto &&curr: base()) { + if(auto elem = curr.second.data(id); elem) { + return elem; + } + } + + return meta_data{}; } /** - * @brief Returns a range to use to visit top-level functions. - * @return An iterable range to use to visit top-level functions. + * @brief Returns a range to visit registered top-level functions. + * @return An iterable range to visit registered top-level functions. */ - [[nodiscard]] meta_range func() const ENTT_NOEXCEPT { - return node->func; + [[nodiscard]] meta_range func() const noexcept { + using return_type = meta_range; + return node.details ? return_type{{*ctx, node.details->func.cbegin()}, {*ctx, node.details->func.cend()}} : return_type{}; } /** - * @brief Returns the function associated with a given identifier. + * @brief Lookup utility for meta functions (bases are also visited). * - * The functions of the base classes will also be visited, if any.
- * In the case of overloaded functions, the first one with the required - * identifier will be returned. + * In case of overloaded functions, the first one with the required + * identifier is returned. * * @param id Unique identifier. - * @return The function associated with the given identifier, if any. + * @return The registered meta function for the given identifier, if any. */ [[nodiscard]] meta_func func(const id_type id) const { - return internal::meta_visit<&node_type::func>([id](const auto *curr) { return curr->id == id; }, node); + if(node.details) { + if(const auto it = node.details->func.find(id); it != node.details->func.cend()) { + return meta_func{*ctx, it->second}; + } + } + + for(auto &&curr: base()) { + if(auto elem = curr.second.func(id); elem) { + return elem; + } + } + + return meta_func{}; } /** * @brief Creates an instance of the underlying type, if possible. * - * Parameters must be such that a cast or conversion to the required types - * is possible. Otherwise, an empty and thus invalid wrapper is returned. + * If suitable, the implicitly generated default constructor is used. + * + * @warning + * The context of the arguments is **not** changed.
+ * It's up to the caller to bind them to the right context(s). * * @param args Parameters to use to construct the instance. * @param sz Number of parameters to use to construct the instance. * @return A wrapper containing the new instance, if any. */ - [[nodiscard]] meta_any construct(meta_any * const args, const size_type sz) const { - meta_any ret{}; - internal::meta_visit<&node_type::ctor>([args, sz, &ret](const auto *curr) { return (curr->arity == sz) && (ret = curr->invoke(args)); }, node); - return ret; + [[nodiscard]] meta_any construct(meta_any *const args, const size_type sz) const { + if(node.details) { + if(const auto *candidate = lookup(args, sz, false, [first = node.details->ctor.cbegin(), last = node.details->ctor.cend()]() mutable { return first == last ? nullptr : &(first++)->second; }); candidate) { + return candidate->invoke(*ctx, args); + } + } + + if(sz == 0u && node.default_constructor) { + return node.default_constructor(*ctx); + } + + return meta_any{meta_ctx_arg, *ctx}; } /** * @copybrief construct - * - * @sa construct - * * @tparam Args Types of arguments to use to construct the instance. * @param args Parameters to use to construct the instance. * @return A wrapper containing the new instance, if any. */ template - [[nodiscard]] meta_any construct(Args &&... args) const { - meta_any arguments[sizeof...(Args) + 1u]{std::forward(args)...}; + [[nodiscard]] meta_any construct(Args &&...args) const { + meta_any arguments[sizeof...(Args) + 1u]{{*ctx, std::forward(args)}...}; return construct(arguments, sizeof...(Args)); } + /** + * @brief Wraps an opaque element of the underlying type. + * @param element A valid pointer to an element of the underlying type. + * @return A wrapper that references the given instance. + */ + meta_any from_void(void *element) const { + return (element && node.from_void) ? node.from_void(*ctx, element, nullptr) : meta_any{meta_ctx_arg, *ctx}; + } + + /*! @copydoc from_void */ + meta_any from_void(const void *element) const { + return (element && node.from_void) ? node.from_void(*ctx, nullptr, element) : meta_any{meta_ctx_arg, *ctx}; + } + /** * @brief Invokes a function given an identifier, if possible. * - * It must be possible to cast the instance to the parent type of the member - * function. Otherwise, invoking the underlying function results in an - * undefined behavior. - * - * @sa meta_func::invoke + * @warning + * The context of the arguments is **not** changed.
+ * It's up to the caller to bind them to the right context(s). * * @param id Unique identifier. * @param instance An opaque instance of the underlying type. @@ -1438,61 +1370,41 @@ public: * @param sz Number of parameters to use to invoke the function. * @return A wrapper containing the returned value, if any. */ - meta_any invoke(const id_type id, meta_handle instance, meta_any * const args, const size_type sz) const { - const internal::meta_func_node* candidate{}; - size_type extent{sz + 1u}; - bool ambiguous{}; - - for(auto *it = internal::meta_visit<&node_type::func>([id, sz](const auto *curr) { return curr->id == id && curr->arity == sz; }, node); it && it->id == id && it->arity == sz; it = it->next) { - size_type direct{}; - size_type ext{}; - - for(size_type next{}; next < sz && next == (direct + ext); ++next) { - const auto type = args[next].type(); - const auto req = it->arg(next).info(); - type.info() == req ? ++direct : (ext += can_cast_or_convert(type.node, req)); - } - - if((direct + ext) == sz) { - if(ext < extent) { - candidate = it; - extent = ext; - ambiguous = false; - } else if(ext == extent) { - ambiguous = true; + meta_any invoke(const id_type id, meta_handle instance, meta_any *const args, const size_type sz) const { + if(node.details) { + if(auto it = node.details->func.find(id); it != node.details->func.cend()) { + if(const auto *candidate = lookup(args, sz, (instance->data() == nullptr), [curr = &it->second]() mutable { return curr ? std::exchange(curr, curr->next.get()) : nullptr; }); candidate) { + return candidate->invoke(*ctx, meta_handle{*ctx, std::move(instance)}, args); } } } - return (candidate && !ambiguous) ? candidate->invoke(std::move(instance), args) : meta_any{}; + for(auto &&curr: base()) { + if(auto elem = curr.second.invoke(id, *instance.operator->(), args, sz); elem) { + return elem; + } + } + + return meta_any{meta_ctx_arg, *ctx}; } /** * @copybrief invoke * - * @sa invoke - * * @param id Unique identifier. * @tparam Args Types of arguments to use to invoke the function. * @param instance An opaque instance of the underlying type. * @param args Parameters to use to invoke the function. - * @return A wrapper containing the new instance, if any. + * @return A wrapper containing the returned value, if any. */ template - meta_any invoke(const id_type id, meta_handle instance, Args &&... args) const { - meta_any arguments[sizeof...(Args) + 1u]{std::forward(args)...}; - return invoke(id, std::move(instance), arguments, sizeof...(Args)); + meta_any invoke(const id_type id, meta_handle instance, Args &&...args) const { + meta_any arguments[sizeof...(Args) + 1u]{{*ctx, std::forward(args)}...}; + return invoke(id, meta_handle{*ctx, std::move(instance)}, arguments, sizeof...(Args)); } /** * @brief Sets the value of a given variable. - * - * It must be possible to cast the instance to the parent type of the data - * member. Otherwise, invoking the setter results in an undefined - * behavior.
- * The type of the value must be such that a cast or conversion to the type - * of the variable is possible. Otherwise, invoking the setter does nothing. - * * @tparam Type Type of value to assign. * @param id Unique identifier. * @param instance An opaque instance of the underlying type. @@ -1507,45 +1419,51 @@ public: /** * @brief Gets the value of a given variable. - * - * It must be possible to cast the instance to the parent type of the data - * member. Otherwise, invoking the getter results in an undefined behavior. - * * @param id Unique identifier. * @param instance An opaque instance of the underlying type. * @return A wrapper containing the value of the underlying variable. */ [[nodiscard]] meta_any get(const id_type id, meta_handle instance) const { const auto candidate = data(id); - return candidate ? candidate.get(std::move(instance)) : meta_any{}; + return candidate ? candidate.get(std::move(instance)) : meta_any{meta_ctx_arg, *ctx}; } /** - * @brief Returns a range to use to visit top-level properties. - * @return An iterable range to use to visit top-level properties. + * @brief Returns a range to visit registered top-level meta properties. + * @return An iterable range to visit registered top-level meta properties. */ - [[nodiscard]] meta_range prop() const ENTT_NOEXCEPT { - return node->prop; + [[nodiscard]] meta_range prop() const noexcept { + using range_type = meta_range; + return node.details ? range_type{{*ctx, node.details->prop.cbegin()}, {*ctx, node.details->prop.cend()}} : range_type{}; } /** - * @brief Returns the property associated with a given key. - * - * Properties of the base classes will also be visited, if any. - * + * @brief Lookup utility for meta properties (bases are also visited). * @param key The key to use to search for a property. - * @return The property associated with the given key, if any. + * @return The registered meta property for the given key, if any. */ - [[nodiscard]] meta_prop prop(meta_any key) const { - return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return curr->id == key; }, node); + [[nodiscard]] meta_prop prop(const id_type key) const { + if(node.details) { + if(const auto it = node.details->prop.find(key); it != node.details->prop.cend()) { + return meta_prop{*ctx, it->second}; + } + } + + for(auto &&curr: base()) { + if(auto elem = curr.second.prop(key); elem) { + return elem; + } + } + + return meta_prop{}; } /** * @brief Returns true if an object is valid, false otherwise. * @return True if the object is valid, false otherwise. */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { - return !(node == nullptr); + [[nodiscard]] explicit operator bool() const noexcept { + return !(ctx == nullptr); } /** @@ -1553,674 +1471,479 @@ public: * @param other The object with which to compare. * @return True if the objects refer to the same type, false otherwise. */ - [[nodiscard]] bool operator==(const meta_type &other) const ENTT_NOEXCEPT { - return (!node && !other.node) || (node && other.node && node->info == other.node->info); - } - - /** - * @brief Resets a type and all its parts. - * - * This function resets a type and all its data members, member functions - * and properties, as well as its constructors, destructors and conversion - * functions if any.
- * Base classes aren't reset but the link between the two types is removed. - * - * The type is also removed from the list of searchable types. - */ - void reset() ENTT_NOEXCEPT { - for(auto** it = internal::meta_context::global(); *it; it = &(*it)->next) { - if(*it == node) { - *it = (*it)->next; - break; - } - } - - unregister_all(&node->prop); - unregister_all(&node->base); - unregister_all(&node->conv); - unregister_all<&internal::meta_ctor_node::prop>(&node->ctor); - unregister_all<&internal::meta_data_node::prop>(&node->data); - unregister_all<&internal::meta_func_node::prop>(&node->func); - - node->id = {}; - node->ctor = node->def_ctor; - node->dtor = nullptr; + [[nodiscard]] bool operator==(const meta_type &other) const noexcept { + return (ctx == other.ctx) && ((!node.info && !other.node.info) || (node.info && other.node.info && *node.info == *other.node.info)); } private: - node_type *node; + internal::meta_type_node node; + const meta_ctx *ctx; }; - /** * @brief Checks if two objects refer to the same type. * @param lhs An object, either valid or not. * @param rhs An object, either valid or not. * @return False if the objects refer to the same node, true otherwise. */ -[[nodiscard]] inline bool operator!=(const meta_type &lhs, const meta_type &rhs) ENTT_NOEXCEPT { +[[nodiscard]] inline bool operator!=(const meta_type &lhs, const meta_type &rhs) noexcept { return !(lhs == rhs); } - -[[nodiscard]] inline meta_type meta_any::type() const ENTT_NOEXCEPT { - return node; +[[nodiscard]] inline meta_type meta_any::type() const noexcept { + return node.info ? meta_type{*ctx, node} : meta_type{}; } - template -meta_any meta_any::invoke(const id_type id, Args &&... args) const { +meta_any meta_any::invoke(const id_type id, Args &&...args) const { return type().invoke(id, *this, std::forward(args)...); } - template -meta_any meta_any::invoke(const id_type id, Args &&... args) { +meta_any meta_any::invoke(const id_type id, Args &&...args) { return type().invoke(id, *this, std::forward(args)...); } - template bool meta_any::set(const id_type id, Type &&value) { return type().set(id, *this, std::forward(value)); } - [[nodiscard]] inline meta_any meta_any::get(const id_type id) const { return type().get(id, *this); } - [[nodiscard]] inline meta_any meta_any::get(const id_type id) { return type().get(id, *this); } +[[nodiscard]] inline meta_any meta_any::allow_cast(const meta_type &type) const { + if(node.info && *node.info == type.info()) { + return as_ref(); + } -[[nodiscard]] inline meta_type meta_ctor::parent() const ENTT_NOEXCEPT { - return node->parent; + if(const auto *value = data(); node.details) { + if(auto it = node.details->conv.find(type.info().hash()); it != node.details->conv.cend()) { + return it->second.conv(*ctx, data()); + } + + for(auto &&curr: node.details->base) { + const auto &as_const = curr.second.type(internal::meta_context::from(*ctx)).from_void(*ctx, nullptr, curr.second.cast(value)); + + if(auto other = as_const.allow_cast(type); other) { + return other; + } + } + } + + if(node.conversion_helper && (type.is_arithmetic() || type.is_enum())) { + // exploits the fact that arithmetic types and enums are also default constructible + auto other = type.construct(); + ENTT_ASSERT(other.node.conversion_helper, "Conversion helper not found"); + const auto value = node.conversion_helper(nullptr, storage.data()); + other.node.conversion_helper(other.storage.data(), &value); + return other; + } + + return meta_any{meta_ctx_arg, *ctx}; } - -[[nodiscard]] inline meta_type meta_ctor::arg(size_type index) const ENTT_NOEXCEPT { - return index < arity() ? node->arg(index) : meta_type{}; +inline bool meta_any::assign(const meta_any &other) { + auto value = other.allow_cast({*ctx, node}); + return value && storage.assign(std::move(value.storage)); } +inline bool meta_any::assign(meta_any &&other) { + if(*node.info == *other.node.info) { + return storage.assign(std::move(other.storage)); + } -[[nodiscard]] inline meta_type meta_data::parent() const ENTT_NOEXCEPT { - return node->parent; + return assign(std::as_const(other)); } - -[[nodiscard]] inline meta_type meta_data::type() const ENTT_NOEXCEPT { - return node->type(); +[[nodiscard]] inline meta_type meta_data::type() const noexcept { + return meta_type{*ctx, node->type(internal::meta_context::from(*ctx))}; } - -[[nodiscard]] inline meta_type meta_func::parent() const ENTT_NOEXCEPT { - return node->parent; +[[nodiscard]] inline meta_type meta_data::arg(const size_type index) const noexcept { + return index < arity() ? node->arg(*ctx, index) : meta_type{}; } - -[[nodiscard]] inline meta_type meta_func::ret() const ENTT_NOEXCEPT { - return node->ret(); +[[nodiscard]] inline meta_type meta_func::ret() const noexcept { + return meta_type{*ctx, node->ret(internal::meta_context::from(*ctx))}; } - -[[nodiscard]] inline meta_type meta_func::arg(size_type index) const ENTT_NOEXCEPT { - return index < arity() ? node->arg(index) : meta_type{}; +[[nodiscard]] inline meta_type meta_func::arg(const size_type index) const noexcept { + return index < arity() ? node->arg(*ctx, index) : meta_type{}; } +/** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ -/*! @brief Opaque iterator for sequence containers. */ -class meta_sequence_container::meta_iterator { - /*! @brief A sequence container can access the underlying iterator. */ +class meta_sequence_container::meta_iterator final { friend class meta_sequence_container; - enum class operation { INCR, DEREF }; + enum class operation : std::uint8_t { + incr, + deref + }; - using vtable_type = void(const operation, const any &, void *); + using vtable_type = void(const operation, const any &, const std::ptrdiff_t, meta_any *); template - static void basic_vtable(const operation op, const any &from, void *to) { + static void basic_vtable(const operation op, const any &value, const std::ptrdiff_t offset, meta_any *other) { switch(op) { - case operation::INCR: - ++any_cast(const_cast(from)); + case operation::incr: { + auto &it = any_cast(const_cast(value)); + it = std::next(it, offset); + } break; + case operation::deref: { + const auto &it = any_cast(value); + other->emplace(*it); + } break; + } + } + +public: + using difference_type = std::ptrdiff_t; + using value_type = meta_any; + using pointer = input_iterator_pointer; + using reference = value_type; + using iterator_category = std::input_iterator_tag; + + constexpr meta_iterator() noexcept + : ctx{}, + vtable{}, + handle{} {} + + template + explicit meta_iterator(const meta_ctx &area, It iter) noexcept + : ctx{&area}, + vtable{&basic_vtable}, + handle{std::move(iter)} {} + + meta_iterator &operator++() noexcept { + vtable(operation::incr, handle, 1, nullptr); + return *this; + } + + meta_iterator operator++(int value) noexcept { + meta_iterator orig = *this; + vtable(operation::incr, handle, ++value, nullptr); + return orig; + } + + meta_iterator &operator--() noexcept { + vtable(operation::incr, handle, -1, nullptr); + return *this; + } + + meta_iterator operator--(int value) noexcept { + meta_iterator orig = *this; + vtable(operation::incr, handle, --value, nullptr); + return orig; + } + + [[nodiscard]] reference operator*() const { + reference other{meta_ctx_arg, *ctx}; + vtable(operation::deref, handle, 0, &other); + return other; + } + + [[nodiscard]] pointer operator->() const { + return operator*(); + } + + [[nodiscard]] explicit operator bool() const noexcept { + return static_cast(handle); + } + + [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept { + return handle == other.handle; + } + + [[nodiscard]] bool operator!=(const meta_iterator &other) const noexcept { + return !(*this == other); + } + +private: + const meta_ctx *ctx; + vtable_type *vtable; + any handle; +}; + +class meta_associative_container::meta_iterator final { + enum class operation : std::uint8_t { + incr, + deref + }; + + using vtable_type = void(const operation, const any &, std::pair *); + + template + static void basic_vtable(const operation op, const any &value, std::pair *other) { + switch(op) { + case operation::incr: + ++any_cast(const_cast(value)); break; - case operation::DEREF: - static_cast(to)->emplace::reference>(*any_cast(from)); + case operation::deref: + const auto &it = any_cast(value); + if constexpr(KeyOnly) { + other->first.emplace(*it); + } else { + other->first.emplacefirst))>(it->first); + other->second.emplacesecond))>(it->second); + } break; } } public: - /*! @brief Signed integer type. */ using difference_type = std::ptrdiff_t; - /*! @brief Type of elements returned by the iterator. */ - using value_type = meta_any; - /*! @brief Pointer type, `void` on purpose. */ - using pointer = void; - /*! @brief Reference type, it is **not** an actual reference. */ + using value_type = std::pair; + using pointer = input_iterator_pointer; using reference = value_type; - /*! @brief Iterator category. */ using iterator_category = std::input_iterator_tag; - /*! @brief Default constructor. */ - meta_iterator() ENTT_NOEXCEPT = default; + constexpr meta_iterator() noexcept + : ctx{}, + vtable{}, + handle{} {} - /** - * @brief Constructs a meta iterator from a given iterator. - * @tparam It Type of actual iterator with which to build the meta iterator. - * @param iter The actual iterator with which to build the meta iterator. - */ - template - meta_iterator(It iter) - : vtable{&basic_vtable}, - handle{std::move(iter)} - {} + template + meta_iterator(const meta_ctx &area, std::integral_constant, It iter) noexcept + : ctx{&area}, + vtable{&basic_vtable}, + handle{std::move(iter)} {} - /*! @brief Pre-increment operator. @return This iterator. */ - meta_iterator & operator++() ENTT_NOEXCEPT { - return vtable(operation::INCR, handle, nullptr), *this; + meta_iterator &operator++() noexcept { + vtable(operation::incr, handle, nullptr); + return *this; } - /*! @brief Post-increment operator. @return This iterator. */ - meta_iterator operator++(int) ENTT_NOEXCEPT { + meta_iterator operator++(int) noexcept { meta_iterator orig = *this; return ++(*this), orig; } - /** - * @brief Checks if two iterators refer to the same element. - * @param other The iterator with which to compare. - * @return True if the iterators refer to the same element, false otherwise. - */ - [[nodiscard]] bool operator==(const meta_iterator &other) const ENTT_NOEXCEPT { - return handle == other.handle; - } - - /** - * @brief Checks if two iterators refer to the same element. - * @param other The iterator with which to compare. - * @return False if the iterators refer to the same element, true otherwise. - */ - [[nodiscard]] bool operator!=(const meta_iterator &other) const ENTT_NOEXCEPT { - return !(*this == other); - } - - /** - * @brief Indirection operator. - * @return The element to which the iterator points. - */ [[nodiscard]] reference operator*() const { - meta_any other; - vtable(operation::DEREF, handle, &other); + reference other{{meta_ctx_arg, *ctx}, {meta_ctx_arg, *ctx}}; + vtable(operation::deref, handle, &other); return other; } - /** - * @brief Returns false if an iterator is invalid, true otherwise. - * @return False if the iterator is invalid, true otherwise. - */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { + [[nodiscard]] pointer operator->() const { + return operator*(); + } + + [[nodiscard]] explicit operator bool() const noexcept { return static_cast(handle); } + [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept { + return handle == other.handle; + } + + [[nodiscard]] bool operator!=(const meta_iterator &other) const noexcept { + return !(*this == other); + } + private: - vtable_type *vtable{}; - any handle{}; -}; - - -template -struct meta_sequence_container::meta_sequence_container_proxy { - using traits_type = meta_sequence_container_traits; - - [[nodiscard]] static meta_type value_type() ENTT_NOEXCEPT { - return internal::meta_info::resolve(); - } - - [[nodiscard]] static size_type size(const any &container) ENTT_NOEXCEPT { - return traits_type::size(any_cast(container)); - } - - [[nodiscard]] static bool resize(any &container, size_type sz) { - auto * const cont = any_cast(&container); - return cont && traits_type::resize(*cont, sz); - } - - [[nodiscard]] static bool clear(any &container) { - auto * const cont = any_cast(&container); - return cont && traits_type::clear(*cont); - } - - [[nodiscard]] static iterator begin(any &container) { - if(auto * const cont = any_cast(&container); cont) { - return iterator{traits_type::begin(*cont)}; - } - - return iterator{traits_type::cbegin(any_cast(container))}; - } - - [[nodiscard]] static iterator end(any &container) { - if(auto * const cont = any_cast(&container); cont) { - return iterator{traits_type::end(*cont)}; - } - - return iterator{traits_type::cend(any_cast(container))}; - } - - [[nodiscard]] static std::pair insert(any &container, iterator it, meta_any &value) { - if(auto * const cont = any_cast(&container); cont) { - // this abomination is necessary because only on macos value_type and const_reference are different types for std::vector - if(value.allow_cast() || value.allow_cast()) { - const auto *element = value.try_cast>(); - auto ret = traits_type::insert(*cont, any_cast(it.handle), element ? *element : value.cast()); - return { iterator{std::move(ret.first)}, ret.second }; - } - } - - return {}; - } - - [[nodiscard]] static std::pair erase(any &container, iterator it) { - if(auto * const cont = any_cast(&container); cont) { - auto ret = traits_type::erase(*cont, any_cast(it.handle)); - return { iterator{std::move(ret.first)}, ret.second }; - } - - return {}; - } - - [[nodiscard]] static meta_any get(any &container, size_type pos) { - if(auto * const cont = any_cast(&container); cont) { - return meta_any{std::in_place_type, traits_type::get(*cont, pos)}; - } - - return meta_any{std::in_place_type, traits_type::cget(any_cast(container), pos)}; - } + const meta_ctx *ctx; + vtable_type *vtable; + any handle; }; +/** + * Internal details not to be documented. + * @endcond + */ /** * @brief Returns the meta value type of a container. * @return The meta value type of the container. */ -[[nodiscard]] inline meta_type meta_sequence_container::value_type() const ENTT_NOEXCEPT { - return value_type_fn(); +[[nodiscard]] inline meta_type meta_sequence_container::value_type() const noexcept { + return value_type_node ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{}; } - /** * @brief Returns the size of a container. * @return The size of the container. */ -[[nodiscard]] inline meta_sequence_container::size_type meta_sequence_container::size() const ENTT_NOEXCEPT { +[[nodiscard]] inline meta_sequence_container::size_type meta_sequence_container::size() const noexcept { return size_fn(storage); } - /** * @brief Resizes a container to contain a given number of elements. * @param sz The new size of the container. * @return True in case of success, false otherwise. */ -inline bool meta_sequence_container::resize(size_type sz) { +inline bool meta_sequence_container::resize(const size_type sz) { return resize_fn(storage, sz); } - /** * @brief Clears the content of a container. * @return True in case of success, false otherwise. */ inline bool meta_sequence_container::clear() { - return clear_fn(storage); + return resize_fn(storage, 0u); } - /** * @brief Returns an iterator to the first element of a container. * @return An iterator to the first element of the container. */ [[nodiscard]] inline meta_sequence_container::iterator meta_sequence_container::begin() { - return begin_fn(storage); + return iter_fn(*ctx, storage, false); } - /** * @brief Returns an iterator that is past the last element of a container. * @return An iterator that is past the last element of the container. */ [[nodiscard]] inline meta_sequence_container::iterator meta_sequence_container::end() { - return end_fn(storage); + return iter_fn(*ctx, storage, true); } - /** * @brief Inserts an element at a specified location of a container. * @param it Iterator before which the element will be inserted. * @param value Element value to insert. - * @return A pair consisting of an iterator to the inserted element (in case of - * success) and a bool denoting whether the insertion took place. + * @return A possibly invalid iterator to the inserted element. */ -inline std::pair meta_sequence_container::insert(iterator it, meta_any value) { - return insert_fn(storage, it, value); +inline meta_sequence_container::iterator meta_sequence_container::insert(iterator it, meta_any value) { + return insert_or_erase_fn(*ctx, storage, it.handle, value); } - /** * @brief Removes a given element from a container. * @param it Iterator to the element to remove. - * @return A pair consisting of an iterator following the last removed element - * (in case of success) and a bool denoting whether the insertion took place. + * @return A possibly invalid iterator following the last removed element. */ -inline std::pair meta_sequence_container::erase(iterator it) { - return erase_fn(storage, it); +inline meta_sequence_container::iterator meta_sequence_container::erase(iterator it) { + return insert(std::move(it), {}); } - /** * @brief Returns a reference to the element at a given location of a container * (no bounds checking is performed). * @param pos The position of the element to return. * @return A reference to the requested element properly wrapped. */ -[[nodiscard]] inline meta_any meta_sequence_container::operator[](size_type pos) { - return get_fn(storage, pos); +[[nodiscard]] inline meta_any meta_sequence_container::operator[](const size_type pos) { + auto it = begin(); + it.operator++(static_cast(pos) - 1); + return *it; } - /** * @brief Returns false if a proxy is invalid, true otherwise. * @return False if the proxy is invalid, true otherwise. */ -[[nodiscard]] inline meta_sequence_container::operator bool() const ENTT_NOEXCEPT { +[[nodiscard]] inline meta_sequence_container::operator bool() const noexcept { return static_cast(storage); } - -/*! @brief Opaque iterator for associative containers. */ -class meta_associative_container::meta_iterator { - enum operation { INCR, DEREF }; - - using vtable_type = void(const operation, const any &, void *); - - template - static void basic_vtable(const operation op, const any &from, void *to) { - switch(op) { - case operation::INCR: - ++any_cast(const_cast(from)); - break; - case operation::DEREF: - const auto &it = any_cast(from); - if constexpr(KeyOnly) { - static_cast *>(to)->first.emplace(*it); - } else { - static_cast *>(to)->first.emplacefirst))>(it->first); - static_cast *>(to)->second.emplacesecond))>(it->second); - } - break; - } - } - -public: - /*! @brief Signed integer type. */ - using difference_type = std::ptrdiff_t; - /*! @brief Type of elements returned by the iterator. */ - using value_type = std::pair; - /*! @brief Pointer type, `void` on purpose. */ - using pointer = void; - /*! @brief Reference type, it is **not** an actual reference. */ - using reference = value_type; - /*! @brief Iterator category. */ - using iterator_category = std::input_iterator_tag; - - /*! @brief Default constructor. */ - meta_iterator() ENTT_NOEXCEPT = default; - - /** - * @brief Constructs an meta iterator from a given iterator. - * @tparam KeyOnly True if the container is also key-only, false otherwise. - * @tparam It Type of actual iterator with which to build the meta iterator. - * @param iter The actual iterator with which to build the meta iterator. - */ - template - meta_iterator(std::integral_constant, It iter) - : vtable{&basic_vtable}, - handle{std::move(iter)} - {} - - /*! @brief Pre-increment operator. @return This iterator. */ - meta_iterator & operator++() ENTT_NOEXCEPT { - return vtable(operation::INCR, handle, nullptr), *this; - } - - /*! @brief Post-increment operator. @return This iterator. */ - meta_iterator operator++(int) ENTT_NOEXCEPT { - meta_iterator orig = *this; - return ++(*this), orig; - } - - /** - * @brief Checks if two iterators refer to the same element. - * @param other The iterator with which to compare. - * @return True if the iterators refer to the same element, false otherwise. - */ - [[nodiscard]] bool operator==(const meta_iterator &other) const ENTT_NOEXCEPT { - return handle == other.handle; - } - - /** - * @brief Checks if two iterators refer to the same element. - * @param other The iterator with which to compare. - * @return False if the iterators refer to the same element, true otherwise. - */ - [[nodiscard]] bool operator!=(const meta_iterator &other) const ENTT_NOEXCEPT { - return !(*this == other); - } - - /** - * @brief Indirection operator. - * @return The element to which the iterator points. - */ - [[nodiscard]] reference operator*() const { - reference other; - vtable(operation::DEREF, handle, &other); - return other; - } - - /** - * @brief Returns false if an iterator is invalid, true otherwise. - * @return False if the iterator is invalid, true otherwise. - */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { - return static_cast(handle); - } - -private: - vtable_type *vtable{}; - any handle{}; -}; - - -template -struct meta_associative_container::meta_associative_container_proxy { - using traits_type = meta_associative_container_traits; - - [[nodiscard]] static meta_type key_type() ENTT_NOEXCEPT { - return internal::meta_info::resolve(); - } - - [[nodiscard]] static meta_type mapped_type() ENTT_NOEXCEPT { - if constexpr(is_key_only_meta_associative_container_v) { - return meta_type{}; - } else { - return internal::meta_info::resolve(); - } - } - - [[nodiscard]] static meta_type value_type() ENTT_NOEXCEPT { - return internal::meta_info::resolve(); - } - - [[nodiscard]] static size_type size(const any &container) ENTT_NOEXCEPT { - return traits_type::size(any_cast(container)); - } - - [[nodiscard]] static bool clear(any &container) { - auto * const cont = any_cast(&container); - return cont && traits_type::clear(*cont); - } - - [[nodiscard]] static iterator begin(any &container) { - if(auto * const cont = any_cast(&container); cont) { - return iterator{is_key_only_meta_associative_container{}, traits_type::begin(*cont)}; - } - - return iterator{is_key_only_meta_associative_container{}, traits_type::cbegin(any_cast(container))}; - } - - [[nodiscard]] static iterator end(any &container) { - if(auto * const cont = any_cast(&container); cont) { - return iterator{is_key_only_meta_associative_container{}, traits_type::end(*cont)}; - } - - return iterator{is_key_only_meta_associative_container{}, traits_type::cend(any_cast(container))}; - } - - [[nodiscard]] static bool insert(any &container, meta_any &key, meta_any &value) { - if(auto * const cont = any_cast(&container); cont && key.allow_cast()) { - if constexpr(is_key_only_meta_associative_container_v) { - return traits_type::insert(*cont, key.cast()); - } else { - return value.allow_cast() - && traits_type::insert(*cont, key.cast(), value.cast()); - } - } - - return false; - } - - [[nodiscard]] static bool erase(any &container, meta_any &key) { - if(auto * const cont = any_cast(&container); cont && key.allow_cast()) { - return traits_type::erase(*cont, key.cast()); - } - - return false; - } - - [[nodiscard]] static iterator find(any &container, meta_any &key) { - if(key.allow_cast()) { - if(auto * const cont = any_cast(&container); cont) { - return iterator{is_key_only_meta_associative_container{}, traits_type::find(*cont, key.cast())}; - } - - return iterator{is_key_only_meta_associative_container{}, traits_type::cfind(any_cast(container), key.cast())}; - } - - return {}; - } -}; - - /** * @brief Returns true if a container is also key-only, false otherwise. * @return True if the associative container is also key-only, false otherwise. */ -[[nodiscard]] inline bool meta_associative_container::key_only() const ENTT_NOEXCEPT { +[[nodiscard]] inline bool meta_associative_container::key_only() const noexcept { return key_only_container; } - /** * @brief Returns the meta key type of a container. * @return The meta key type of the a container. */ -[[nodiscard]] inline meta_type meta_associative_container::key_type() const ENTT_NOEXCEPT { - return key_type_fn(); +[[nodiscard]] inline meta_type meta_associative_container::key_type() const noexcept { + return key_type_node ? meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))} : meta_type{}; } - /** * @brief Returns the meta mapped type of a container. * @return The meta mapped type of the a container. */ -[[nodiscard]] inline meta_type meta_associative_container::mapped_type() const ENTT_NOEXCEPT { - return mapped_type_fn(); +[[nodiscard]] inline meta_type meta_associative_container::mapped_type() const noexcept { + return mapped_type_node ? meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))} : meta_type{}; } - /*! @copydoc meta_sequence_container::value_type */ -[[nodiscard]] inline meta_type meta_associative_container::value_type() const ENTT_NOEXCEPT { - return value_type_fn(); +[[nodiscard]] inline meta_type meta_associative_container::value_type() const noexcept { + return value_type_node ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{}; } - /*! @copydoc meta_sequence_container::size */ -[[nodiscard]] inline meta_associative_container::size_type meta_associative_container::size() const ENTT_NOEXCEPT { +[[nodiscard]] inline meta_associative_container::size_type meta_associative_container::size() const noexcept { return size_fn(storage); } - /*! @copydoc meta_sequence_container::clear */ inline bool meta_associative_container::clear() { return clear_fn(storage); } - /*! @copydoc meta_sequence_container::begin */ [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::begin() { - return begin_fn(storage); + return iter_fn(*ctx, storage, false); } - /*! @copydoc meta_sequence_container::end */ [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::end() { - return end_fn(storage); + return iter_fn(*ctx, storage, true); } +/** + * @brief Inserts a key only element into a container. + * @param key The key of the element to insert. + * @return A bool denoting whether the insertion took place. + */ +inline bool meta_associative_container::insert(meta_any key) { + meta_any value{*ctx, std::in_place_type}; + return (insert_or_erase_fn(storage, key, value) != 0u); +} /** - * @brief Inserts an element (a key/value pair) into a container. + * @brief Inserts a key/value element into a container. * @param key The key of the element to insert. * @param value The value of the element to insert. * @return A bool denoting whether the insertion took place. */ -inline bool meta_associative_container::insert(meta_any key, meta_any value = {}) { - return insert_fn(storage, key, value); +inline bool meta_associative_container::insert(meta_any key, meta_any value) { + return (insert_or_erase_fn(storage, key, value) != 0u); } - /** * @brief Removes the specified element from a container. * @param key The key of the element to remove. * @return A bool denoting whether the removal took place. */ -inline bool meta_associative_container::erase(meta_any key) { - return erase_fn(storage, key); +inline meta_associative_container::size_type meta_associative_container::erase(meta_any key) { + return insert(std::move(key), meta_any{meta_ctx_arg, *ctx}); } - /** * @brief Returns an iterator to the element with a given key, if any. * @param key The key of the element to search. * @return An iterator to the element with the given key, if any. */ [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::find(meta_any key) { - return find_fn(storage, key); + return find_fn(*ctx, storage, key); } - /** * @brief Returns false if a proxy is invalid, true otherwise. * @return False if the proxy is invalid, true otherwise. */ -[[nodiscard]] inline meta_associative_container::operator bool() const ENTT_NOEXCEPT { +[[nodiscard]] inline meta_associative_container::operator bool() const noexcept { return static_cast(storage); } - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/meta/node.hpp b/LiteLoader/third-party/include/entt/meta/node.hpp index b967d13..4dfdd54 100644 --- a/LiteLoader/third-party/include/entt/meta/node.hpp +++ b/LiteLoader/third-party/include/entt/meta/node.hpp @@ -1,158 +1,157 @@ #ifndef ENTT_META_NODE_HPP #define ENTT_META_NODE_HPP - #include +#include #include #include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/attribute.h" -#include "third-party/include/entt/core/fwd.hpp" -#include "third-party/include/entt/core/type_info.hpp" -#include "third-party/include/entt/core/type_traits.hpp" +#include "../config/config.h" +#include "../container/dense_map.hpp" +#include "../core/attribute.h" +#include "../core/enum.hpp" +#include "../core/fwd.hpp" +#include "../core/type_info.hpp" +#include "../core/type_traits.hpp" +#include "../core/utility.hpp" +#include "context.hpp" #include "type_traits.hpp" - namespace entt { - class meta_any; class meta_type; struct meta_handle; - /** * @cond TURN_OFF_DOXYGEN * Internal details not to be documented. */ - namespace internal { +enum class meta_traits : std::uint32_t { + is_none = 0x0000, + is_const = 0x0001, + is_static = 0x0002, + is_arithmetic = 0x0004, + is_integral = 0x0008, + is_signed = 0x0010, + is_array = 0x0020, + is_enum = 0x0040, + is_class = 0x0080, + is_meta_pointer_like = 0x0100, + is_meta_sequence_container = 0x0200, + is_meta_associative_container = 0x0400, + _entt_enum_as_bitmask +}; struct meta_type_node; - struct meta_prop_node { - meta_prop_node * next; - const meta_any &id; - meta_any &value; + meta_type_node (*type)(const meta_context &) noexcept {}; + std::shared_ptr value{}; }; - struct meta_base_node { - meta_type_node * const parent; - meta_base_node * next; - meta_type_node *(* const type)() ENTT_NOEXCEPT; - const void *(* const cast)(const void *) ENTT_NOEXCEPT; + meta_type_node (*type)(const meta_context &) noexcept {}; + const void *(*cast)(const void *) noexcept {}; }; - struct meta_conv_node { - meta_type_node * const parent; - meta_conv_node * next; - meta_type_node *(* const type)() ENTT_NOEXCEPT; - meta_any(* const conv)(const void *); + meta_any (*conv)(const meta_ctx &, const void *){}; }; - struct meta_ctor_node { using size_type = std::size_t; - meta_type_node * const parent; - meta_ctor_node * next; - meta_prop_node * prop; - const size_type arity; - meta_type(* const arg)(const size_type) ENTT_NOEXCEPT; - meta_any(* const invoke)(meta_any * const); + + size_type arity{0u}; + meta_type (*arg)(const meta_ctx &, const size_type) noexcept {}; + meta_any (*invoke)(const meta_ctx &, meta_any *const){}; }; +struct meta_dtor_node { + void (*dtor)(void *){}; +}; struct meta_data_node { - id_type id; - meta_type_node * const parent; - meta_data_node * next; - meta_prop_node * prop; - const bool is_const; - const bool is_static; - meta_type_node *(* const type)() ENTT_NOEXCEPT; - bool(* const set)(meta_handle, meta_any); - meta_any(* const get)(meta_handle); -}; + using size_type = std::size_t; + meta_traits traits{meta_traits::is_none}; + size_type arity{0u}; + meta_type_node (*type)(const meta_context &) noexcept {}; + meta_type (*arg)(const meta_ctx &, const size_type) noexcept {}; + bool (*set)(meta_handle, meta_any){}; + meta_any (*get)(const meta_ctx &, meta_handle){}; + dense_map prop{}; +}; struct meta_func_node { using size_type = std::size_t; - id_type id; - meta_type_node * const parent; - meta_func_node * next; - meta_prop_node * prop; - const size_type arity; - const bool is_const; - const bool is_static; - meta_type_node *(* const ret)() ENTT_NOEXCEPT; - meta_type(* const arg)(const size_type) ENTT_NOEXCEPT; - meta_any(* const invoke)(meta_handle, meta_any *); + + meta_traits traits{meta_traits::is_none}; + size_type arity{0u}; + meta_type_node (*ret)(const meta_context &) noexcept {}; + meta_type (*arg)(const meta_ctx &, const size_type) noexcept {}; + meta_any (*invoke)(const meta_ctx &, meta_handle, meta_any *const){}; + std::shared_ptr next{}; + dense_map prop{}; }; - -struct meta_template_info { +struct meta_template_node { using size_type = std::size_t; - const bool is_template_specialization; - const size_type arity; - meta_type_node *(* const type)() ENTT_NOEXCEPT; - meta_type_node *(* const arg)(const size_type) ENTT_NOEXCEPT; + + size_type arity{0u}; + meta_type_node (*type)(const meta_context &) noexcept {}; + meta_type_node (*arg)(const meta_context &, const size_type) noexcept {}; }; +struct meta_type_descriptor { + dense_map ctor{}; + dense_map base{}; + dense_map conv{}; + dense_map data{}; + dense_map func{}; + dense_map prop{}; +}; struct meta_type_node { using size_type = std::size_t; - const type_info info; - id_type id; - meta_type_node * next; - meta_prop_node * prop; - const size_type size_of; - const bool is_void; - const bool is_integral; - const bool is_floating_point; - const bool is_array; - const bool is_enum; - const bool is_union; - const bool is_class; - const bool is_pointer; - const bool is_function_pointer; - const bool is_member_object_pointer; - const bool is_member_function_pointer; - const bool is_pointer_like; - const bool is_sequence_container; - const bool is_associative_container; - const meta_template_info template_info; - const size_type rank; - size_type(* const extent)(const size_type) ENTT_NOEXCEPT ; - meta_type_node *(* const remove_pointer)() ENTT_NOEXCEPT; - meta_type_node *(* const remove_extent)() ENTT_NOEXCEPT; - meta_ctor_node * const def_ctor; - meta_ctor_node *ctor{nullptr}; - meta_base_node *base{nullptr}; - meta_conv_node *conv{nullptr}; - meta_data_node *data{nullptr}; - meta_func_node *func{nullptr}; - void(* dtor)(void *){nullptr}; + + const type_info *info{}; + id_type id{}; + meta_traits traits{meta_traits::is_none}; + size_type size_of{0u}; + meta_type_node (*resolve)(const meta_context &) noexcept {}; + meta_type_node (*remove_pointer)(const meta_context &) noexcept {}; + meta_any (*default_constructor)(const meta_ctx &){}; + double (*conversion_helper)(void *, const void *){}; + meta_any (*from_void)(const meta_ctx &, void *, const void *){}; + meta_template_node templ{}; + meta_dtor_node dtor{}; + std::shared_ptr details{}; }; +template +meta_type_node resolve(const meta_context &) noexcept; -template -auto meta_visit(const Op &op, const Node *node) --> std::decay_t*Member)> { - for(auto *curr = node->*Member; curr; curr = curr->next) { - if(op(curr)) { - return curr; - } +template +[[nodiscard]] auto meta_arg_node(const meta_context &context, type_list, [[maybe_unused]] const std::size_t index) noexcept { + std::size_t pos{}; + meta_type_node (*value)(const meta_context &) noexcept = nullptr; + ((value = (pos++ == index ? &resolve>> : value)), ...); + ENTT_ASSERT(value != nullptr, "Out of bounds"); + return value(context); +} + +[[nodiscard]] inline const void *try_cast(const meta_context &context, const meta_type_node &from, const meta_type_node &to, const void *instance) noexcept { + if(from.info && to.info && *from.info == *to.info) { + return instance; } - if constexpr(std::is_same_v) { - for(auto *curr = node->base; curr; curr = curr->next) { - if(auto *ret = meta_visit(op, curr->type()); ret) { - return ret; + if(from.details) { + for(auto &&curr: from.details->base) { + if(const void *elem = try_cast(context, curr.second.type(context), to, curr.second.cast(instance)); elem) { + return elem; } } } @@ -160,111 +159,78 @@ auto meta_visit(const Op &op, const Node *node) return nullptr; } - -template -meta_type_node * meta_arg_node(type_list, const std::size_t index) ENTT_NOEXCEPT; - +[[nodiscard]] inline const meta_type_node *try_resolve(const meta_context &context, const type_info &info) noexcept { + const auto it = context.value.find(info.hash()); + return it != context.value.end() ? &it->second : nullptr; +} template -class ENTT_API meta_node { - static_assert(std::is_same_v>>, "Invalid type"); +[[nodiscard]] meta_type_node resolve(const meta_context &context) noexcept { + static_assert(std::is_same_v>>, "Invalid type"); - template - [[nodiscard]] static auto extent(const meta_type_node::size_type dim, std::index_sequence) ENTT_NOEXCEPT { - meta_type_node::size_type ext{}; - ((ext = (dim == Index ? std::extent_v : ext)), ...); - return ext; + if(auto *elem = try_resolve(context, type_id()); elem) { + return *elem; } - [[nodiscard]] static meta_ctor_node * meta_default_constructor([[maybe_unused]] meta_type_node *type) ENTT_NOEXCEPT { - if constexpr(std::is_default_constructible_v) { - static meta_ctor_node node{ - type, - nullptr, - nullptr, - 0u, - nullptr, - [](meta_any * const) { return meta_any{std::in_place_type}; } - }; + meta_type_node node{ + &type_id(), + type_id().hash(), + (std::is_arithmetic_v ? meta_traits::is_arithmetic : meta_traits::is_none) + | (std::is_integral_v ? meta_traits::is_integral : meta_traits::is_none) + | (std::is_signed_v ? meta_traits::is_signed : meta_traits::is_none) + | (std::is_array_v ? meta_traits::is_array : meta_traits::is_none) + | (std::is_enum_v ? meta_traits::is_enum : meta_traits::is_none) + | (std::is_class_v ? meta_traits::is_class : meta_traits::is_none) + | (is_meta_pointer_like_v ? meta_traits::is_meta_pointer_like : meta_traits::is_none) + | (is_complete_v> ? meta_traits::is_meta_sequence_container : meta_traits::is_none) + | (is_complete_v> ? meta_traits::is_meta_associative_container : meta_traits::is_none), + size_of_v, + &resolve, + &resolve>>}; - return &node; - } else { - return nullptr; - } - } - - [[nodiscard]] static meta_template_info meta_template_descriptor() ENTT_NOEXCEPT { - if constexpr(is_complete_v>) { - return { - true, - meta_template_traits::args_type::size, - &meta_node::class_type>::resolve, - [](const std::size_t index) ENTT_NOEXCEPT { - return meta_arg_node(typename meta_template_traits::args_type{}, index); - } - }; - } else { - return { false, 0u, nullptr, nullptr }; - } - } - -public: - [[nodiscard]] static meta_type_node * resolve() ENTT_NOEXCEPT { - static meta_type_node node{ - type_id(), - {}, - nullptr, - nullptr, - size_of_v, - std::is_void_v, - std::is_integral_v, - std::is_floating_point_v, - std::is_array_v, - std::is_enum_v, - std::is_union_v, - std::is_class_v, - std::is_pointer_v, - std::is_pointer_v && std::is_function_v>, - std::is_member_object_pointer_v, - std::is_member_function_pointer_v, - is_meta_pointer_like_v, - is_complete_v>, - is_complete_v>, - meta_template_descriptor(), - std::rank_v, - [](meta_type_node::size_type dim) ENTT_NOEXCEPT { return extent(dim, std::make_index_sequence>{}); }, - &meta_node>>>::resolve, - &meta_node>>>::resolve, - meta_default_constructor(&node), - meta_default_constructor(&node) + if constexpr(std::is_default_constructible_v) { + node.default_constructor = +[](const meta_ctx &ctx) { + return meta_any{ctx, std::in_place_type}; }; - - return &node; } -}; + if constexpr(std::is_arithmetic_v) { + node.conversion_helper = +[](void *bin, const void *value) { + return bin ? static_cast(*static_cast(bin) = static_cast(*static_cast(value))) : static_cast(*static_cast(value)); + }; + } else if constexpr(std::is_enum_v) { + node.conversion_helper = +[](void *bin, const void *value) { + return bin ? static_cast(*static_cast(bin) = static_cast(static_cast>(*static_cast(value)))) : static_cast(*static_cast(value)); + }; + } -template -struct meta_info: meta_node>> {}; - - -template -meta_type_node * meta_arg_node(type_list, const std::size_t index) ENTT_NOEXCEPT { - meta_type_node *args[sizeof...(Args) + 1u]{nullptr, internal::meta_info::resolve()...}; - return args[index + 1u]; -} + if constexpr(!std::is_same_v && !std::is_function_v) { + node.from_void = +[](const meta_ctx &ctx, void *element, const void *as_const) { + if(element) { + return meta_any{ctx, std::in_place_type &>, *static_cast *>(element)}; + } + return meta_any{ctx, std::in_place_type &>, *static_cast *>(as_const)}; + }; + } + if constexpr(is_complete_v>) { + node.templ = meta_template_node{ + meta_template_traits::args_type::size, + &resolve::class_type>, + +[](const meta_context &area, const std::size_t index) noexcept { return meta_arg_node(area, typename meta_template_traits::args_type{}, index); }}; + } + + return node; } +} // namespace internal /** * Internal details not to be documented. * @endcond */ - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/meta/pointer.hpp b/LiteLoader/third-party/include/entt/meta/pointer.hpp index 62a2453..58d2f10 100644 --- a/LiteLoader/third-party/include/entt/meta/pointer.hpp +++ b/LiteLoader/third-party/include/entt/meta/pointer.hpp @@ -1,24 +1,19 @@ #ifndef ENTT_META_POINTER_HPP #define ENTT_META_POINTER_HPP - #include #include #include "type_traits.hpp" - namespace entt { - /** * @brief Makes plain pointers pointer-like types for the meta system. * @tparam Type Element type. */ template struct is_meta_pointer_like - : std::true_type -{}; - + : std::true_type {}; /** * @brief Partial specialization used to reject pointers to arrays. @@ -26,10 +21,8 @@ struct is_meta_pointer_like * @tparam N Number of elements of the array. */ template -struct is_meta_pointer_like - : std::false_type -{}; - +struct is_meta_pointer_like + : std::false_type {}; /** * @brief Makes `std::shared_ptr`s of any type pointer-like types for the meta @@ -38,9 +31,7 @@ struct is_meta_pointer_like */ template struct is_meta_pointer_like> - : std::true_type -{}; - + : std::true_type {}; /** * @brief Makes `std::unique_ptr`s of any type pointer-like types for the meta @@ -50,11 +41,8 @@ struct is_meta_pointer_like> */ template struct is_meta_pointer_like> - : std::true_type -{}; - - -} + : std::true_type {}; +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/meta/policy.hpp b/LiteLoader/third-party/include/entt/meta/policy.hpp index 1b7d9c8..0744816 100644 --- a/LiteLoader/third-party/include/entt/meta/policy.hpp +++ b/LiteLoader/third-party/include/entt/meta/policy.hpp @@ -1,27 +1,86 @@ #ifndef ENTT_META_POLICY_HPP #define ENTT_META_POLICY_HPP +#include namespace entt { - /*! @brief Empty class type used to request the _as ref_ policy. */ -struct as_ref_t {}; - +struct as_ref_t final { + /** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + template + static constexpr bool value = std::is_reference_v && !std::is_const_v>; + /** + * Internal details not to be documented. + * @endcond + */ +}; /*! @brief Empty class type used to request the _as cref_ policy. */ -struct as_cref_t {}; - +struct as_cref_t final { + /** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + template + static constexpr bool value = std::is_reference_v; + /** + * Internal details not to be documented. + * @endcond + */ +}; /*! @brief Empty class type used to request the _as-is_ policy. */ -struct as_is_t {}; - +struct as_is_t final { + /** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + template + static constexpr bool value = true; + /** + * Internal details not to be documented. + * @endcond + */ +}; /*! @brief Empty class type used to request the _as void_ policy. */ -struct as_void_t {}; +struct as_void_t final { + /** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + template + static constexpr bool value = true; + /** + * Internal details not to be documented. + * @endcond + */ +}; +/** + * @brief Provides the member constant `value` to true if a type also is a meta + * policy, false otherwise. + * @tparam Type Type to check. + */ +template +struct is_meta_policy + : std::disjunction< + std::is_same, + std::is_same, + std::is_same, + std::is_same> {}; -} +/** + * @brief Helper variable template. + * @tparam Type Type to check. + */ +template +inline constexpr bool is_meta_policy_v = is_meta_policy::value; +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/meta/range.hpp b/LiteLoader/third-party/include/entt/meta/range.hpp index 7b54525..e3d8154 100644 --- a/LiteLoader/third-party/include/entt/meta/range.hpp +++ b/LiteLoader/third-party/include/entt/meta/range.hpp @@ -1,100 +1,150 @@ #ifndef ENTT_META_RANGE_HPP #define ENTT_META_RANGE_HPP - #include #include - +#include +#include "../core/fwd.hpp" +#include "../core/iterator.hpp" +#include "context.hpp" namespace entt { +/** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + +namespace internal { + +template +struct meta_range_iterator final { + using difference_type = std::ptrdiff_t; + using value_type = std::pair; + using pointer = input_iterator_pointer; + using reference = value_type; + using iterator_category = std::input_iterator_tag; + + meta_range_iterator() noexcept + : it{}, + ctx{} {} + + meta_range_iterator(const meta_ctx &area, const It iter) noexcept + : it{iter}, + ctx{&area} {} + + meta_range_iterator &operator++() noexcept { + return ++it, *this; + } + + meta_range_iterator operator++(int) noexcept { + meta_range_iterator orig = *this; + return ++(*this), orig; + } + + constexpr meta_range_iterator &operator--() noexcept { + return --it, *this; + } + + constexpr meta_range_iterator operator--(int) noexcept { + meta_range_iterator orig = *this; + return operator--(), orig; + } + + constexpr meta_range_iterator &operator+=(const difference_type value) noexcept { + it += value; + return *this; + } + + constexpr meta_range_iterator operator+(const difference_type value) const noexcept { + meta_range_iterator copy = *this; + return (copy += value); + } + + constexpr meta_range_iterator &operator-=(const difference_type value) noexcept { + return (*this += -value); + } + + constexpr meta_range_iterator operator-(const difference_type value) const noexcept { + return (*this + -value); + } + + [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept { + return {it[value].first, Type{*ctx, it[value].second}}; + } + + [[nodiscard]] constexpr pointer operator->() const noexcept { + return operator*(); + } + + [[nodiscard]] constexpr reference operator*() const noexcept { + return {it->first, Type{*ctx, it->second}}; + } + + template + friend constexpr std::ptrdiff_t operator-(const meta_range_iterator &, const meta_range_iterator &) noexcept; + + template + friend constexpr bool operator==(const meta_range_iterator &, const meta_range_iterator &) noexcept; + + template + friend constexpr bool operator<(const meta_range_iterator &, const meta_range_iterator &) noexcept; + +private: + It it; + const meta_ctx *ctx; +}; + +template +[[nodiscard]] constexpr std::ptrdiff_t operator-(const meta_range_iterator &lhs, const meta_range_iterator &rhs) noexcept { + return lhs.it - rhs.it; +} + +template +[[nodiscard]] constexpr bool operator==(const meta_range_iterator &lhs, const meta_range_iterator &rhs) noexcept { + return lhs.it == rhs.it; +} + +template +[[nodiscard]] constexpr bool operator!=(const meta_range_iterator &lhs, const meta_range_iterator &rhs) noexcept { + return !(lhs == rhs); +} + +template +[[nodiscard]] constexpr bool operator<(const meta_range_iterator &lhs, const meta_range_iterator &rhs) noexcept { + return lhs.it < rhs.it; +} + +template +[[nodiscard]] constexpr bool operator>(const meta_range_iterator &lhs, const meta_range_iterator &rhs) noexcept { + return rhs < lhs; +} + +template +[[nodiscard]] constexpr bool operator<=(const meta_range_iterator &lhs, const meta_range_iterator &rhs) noexcept { + return !(lhs > rhs); +} + +template +[[nodiscard]] constexpr bool operator>=(const meta_range_iterator &lhs, const meta_range_iterator &rhs) noexcept { + return !(lhs < rhs); +} + +} // namespace internal + +/** + * Internal details not to be documented. + * @endcond + */ /** * @brief Iterable range to use to iterate all types of meta objects. * @tparam Type Type of meta objects returned. - * @tparam Node Type of meta nodes iterated. + * @tparam It Type of forward iterator. */ -template -class meta_range { - struct range_iterator { - using difference_type = std::ptrdiff_t; - using value_type = Type; - using pointer = void; - using reference = value_type; - using iterator_category = std::input_iterator_tag; - using node_type = Node; - - range_iterator() ENTT_NOEXCEPT = default; - - range_iterator(node_type *head) ENTT_NOEXCEPT - : it{head} - {} - - range_iterator & operator++() ENTT_NOEXCEPT { - return (it = it->next), *this; - } - - range_iterator operator++(int) ENTT_NOEXCEPT { - range_iterator orig = *this; - return ++(*this), orig; - } - - [[nodiscard]] reference operator*() const ENTT_NOEXCEPT { - return it; - } - - [[nodiscard]] bool operator==(const range_iterator &other) const ENTT_NOEXCEPT { - return other.it == it; - } - - [[nodiscard]] bool operator!=(const range_iterator &other) const ENTT_NOEXCEPT { - return !(*this == other); - } - - private: - node_type *it{}; - }; - -public: - /*! @brief Node type. */ - using node_type = Node; - /*! @brief Input iterator type. */ - using iterator = range_iterator; - - /*! @brief Default constructor. */ - meta_range() ENTT_NOEXCEPT = default; - - /** - * @brief Constructs a meta range from a given node. - * @param head The underlying node with which to construct the range. - */ - meta_range(node_type *head) - : node{head} - {} - - /** - * @brief Returns an iterator to the beginning. - * @return An iterator to the first meta object of the range. - */ - [[nodiscard]] iterator begin() const ENTT_NOEXCEPT { - return iterator{node}; - } - - /** - * @brief Returns an iterator to the end. - * @return An iterator to the element following the last meta object of the - * range. - */ - [[nodiscard]] iterator end() const ENTT_NOEXCEPT { - return iterator{}; - } - -private: - node_type *node{nullptr}; -}; - - -} +template +using meta_range = iterable_adaptor>; +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/meta/resolve.hpp b/LiteLoader/third-party/include/entt/meta/resolve.hpp index 7ba58d9..9360db5 100644 --- a/LiteLoader/third-party/include/entt/meta/resolve.hpp +++ b/LiteLoader/third-party/include/entt/meta/resolve.hpp @@ -1,17 +1,27 @@ #ifndef ENTT_META_RESOLVE_HPP #define ENTT_META_RESOLVE_HPP - -#include -#include "third-party/include/entt/core/type_info.hpp" -#include "ctx.hpp" +#include +#include "../core/type_info.hpp" +#include "../locator/locator.hpp" +#include "context.hpp" #include "meta.hpp" #include "node.hpp" #include "range.hpp" - namespace entt { +/** + * @brief Returns the meta type associated with a given type. + * @tparam Type Type to use to search for a meta type. + * @param ctx The context from which to search for meta types. + * @return The meta type associated with the given type, if any. + */ +template +[[nodiscard]] meta_type resolve(const meta_ctx &ctx) noexcept { + auto &&context = internal::meta_context::from(ctx); + return {ctx, internal::resolve>>(context)}; +} /** * @brief Returns the meta type associated with a given type. @@ -19,54 +29,74 @@ namespace entt { * @return The meta type associated with the given type, if any. */ template -[[nodiscard]] meta_type resolve() ENTT_NOEXCEPT { - return internal::meta_info::resolve(); +[[nodiscard]] meta_type resolve() noexcept { + return resolve(locator::value_or()); } +/** + * @brief Returns a range to use to visit all meta types. + * @param ctx The context from which to search for meta types. + * @return An iterable range to use to visit all meta types. + */ +[[nodiscard]] inline meta_range resolve(const meta_ctx &ctx) noexcept { + auto &&context = internal::meta_context::from(ctx); + return {{ctx, context.value.cbegin()}, {ctx, context.value.cend()}}; +} /** * @brief Returns a range to use to visit all meta types. * @return An iterable range to use to visit all meta types. */ -[[nodiscard]] inline meta_range resolve() { - return *internal::meta_context::global(); +[[nodiscard]] inline meta_range resolve() noexcept { + return resolve(locator::value_or()); } +/** + * @brief Returns the meta type associated with a given identifier, if any. + * @param ctx The context from which to search for meta types. + * @param id Unique identifier. + * @return The meta type associated with the given identifier, if any. + */ +[[nodiscard]] inline meta_type resolve(const meta_ctx &ctx, const id_type id) noexcept { + for(auto &&curr: resolve(ctx)) { + if(curr.second.id() == id) { + return curr.second; + } + } + + return meta_type{}; +} /** * @brief Returns the meta type associated with a given identifier, if any. * @param id Unique identifier. * @return The meta type associated with the given identifier, if any. */ -[[nodiscard]] inline meta_type resolve(const id_type id) ENTT_NOEXCEPT { - for(auto *curr = *internal::meta_context::global(); curr; curr = curr->next) { - if(curr->id == id) { - return curr; - } - } - - return {}; +[[nodiscard]] inline meta_type resolve(const id_type id) noexcept { + return resolve(locator::value_or(), id); } - /** - * @brief Returns the meta type associated with a given type info object, if - * any. + * @brief Returns the meta type associated with a given type info object. + * @param ctx The context from which to search for meta types. * @param info The type info object of the requested type. * @return The meta type associated with the given type info object, if any. */ -[[nodiscard]] inline meta_type resolve(const type_info info) ENTT_NOEXCEPT { - for(auto *curr = *internal::meta_context::global(); curr; curr = curr->next) { - if(curr->info == info) { - return curr; - } - } - - return {}; +[[nodiscard]] inline meta_type resolve(const meta_ctx &ctx, const type_info &info) noexcept { + auto &&context = internal::meta_context::from(ctx); + const auto *elem = internal::try_resolve(context, info); + return elem ? meta_type{ctx, *elem} : meta_type{}; } - +/** + * @brief Returns the meta type associated with a given type info object. + * @param info The type info object of the requested type. + * @return The meta type associated with the given type info object, if any. + */ +[[nodiscard]] inline meta_type resolve(const type_info &info) noexcept { + return resolve(locator::value_or(), info); } +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/meta/template.hpp b/LiteLoader/third-party/include/entt/meta/template.hpp index 0d27c32..0009b51 100644 --- a/LiteLoader/third-party/include/entt/meta/template.hpp +++ b/LiteLoader/third-party/include/entt/meta/template.hpp @@ -1,24 +1,20 @@ #ifndef ENTT_META_TEMPLATE_HPP #define ENTT_META_TEMPLATE_HPP - -#include "third-party/include/entt/core/type_traits.hpp" - +#include "../core/type_traits.hpp" namespace entt { - /*! @brief Utility class to disambiguate class templates. */ -template typename> +template class> struct meta_class_template_tag {}; - /** * @brief General purpose traits class for generating meta template information. * @tparam Clazz Type of class template. * @tparam Args Types of template arguments. */ -template typename Clazz, typename... Args> +template class Clazz, typename... Args> struct meta_template_traits> { /*! @brief Wrapped class template. */ using class_type = meta_class_template_tag; @@ -26,8 +22,6 @@ struct meta_template_traits> { using args_type = type_list; }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/meta/type_traits.hpp b/LiteLoader/third-party/include/entt/meta/type_traits.hpp index 8fe91aa..51b69f6 100644 --- a/LiteLoader/third-party/include/entt/meta/type_traits.hpp +++ b/LiteLoader/third-party/include/entt/meta/type_traits.hpp @@ -1,13 +1,11 @@ #ifndef ENTT_META_TYPE_TRAITS_HPP #define ENTT_META_TYPE_TRAITS_HPP - #include - +#include namespace entt { - /** * @brief Traits class template to be specialized to enable support for meta * template information. @@ -15,7 +13,6 @@ namespace entt { template struct meta_template_traits; - /** * @brief Traits class template to be specialized to enable support for meta * sequence containers. @@ -23,7 +20,6 @@ struct meta_template_traits; template struct meta_sequence_container_traits; - /** * @brief Traits class template to be specialized to enable support for meta * associative containers. @@ -31,31 +27,6 @@ struct meta_sequence_container_traits; template struct meta_associative_container_traits; - -/** - * @brief Provides the member constant `value` to true if a meta associative - * container claims to wrap a key-only type, false otherwise. - * @tparam Type Potentially key-only meta associative container type. - */ -template -struct is_key_only_meta_associative_container: std::true_type {}; - - -/*! @copydoc is_key_only_meta_associative_container */ -template -struct is_key_only_meta_associative_container::type::mapped_type>> - : std::false_type -{}; - - -/** - * @brief Helper variable template. - * @tparam Type Potentially key-only meta associative container type. - */ -template -inline constexpr auto is_key_only_meta_associative_container_v = is_key_only_meta_associative_container::value; - - /** * @brief Provides the member constant `value` to true if a given type is a * pointer-like type from the point of view of the meta system, false otherwise. @@ -64,7 +35,6 @@ inline constexpr auto is_key_only_meta_associative_container_v = is_key_only_met template struct is_meta_pointer_like: std::false_type {}; - /** * @brief Partial specialization to ensure that const pointer-like types are * also accepted. @@ -73,7 +43,6 @@ struct is_meta_pointer_like: std::false_type {}; template struct is_meta_pointer_like: is_meta_pointer_like {}; - /** * @brief Helper variable template. * @tparam Type Potentially pointer-like type. @@ -81,8 +50,6 @@ struct is_meta_pointer_like: is_meta_pointer_like {}; template inline constexpr auto is_meta_pointer_like_v = is_meta_pointer_like::value; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/meta/utility.hpp b/LiteLoader/third-party/include/entt/meta/utility.hpp index 9925647..3ee98ee 100644 --- a/LiteLoader/third-party/include/entt/meta/utility.hpp +++ b/LiteLoader/third-party/include/entt/meta/utility.hpp @@ -1,25 +1,56 @@ #ifndef ENTT_META_UTILITY_HPP #define ENTT_META_UTILITY_HPP - #include #include #include #include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/type_traits.hpp" +#include "../core/type_traits.hpp" +#include "../locator/locator.hpp" #include "meta.hpp" #include "node.hpp" #include "policy.hpp" - namespace entt { +/** + * @brief Meta function descriptor traits. + * @tparam Ret Function return type. + * @tparam Args Function arguments. + * @tparam Static Function staticness. + * @tparam Const Function constness. + */ +template +struct meta_function_descriptor_traits { + /*! @brief Meta function return type. */ + using return_type = Ret; + /*! @brief Meta function arguments. */ + using args_type = Args; + + /*! @brief True if the meta function is static, false otherwise. */ + static constexpr bool is_static = Static; + /*! @brief True if the meta function is const, false otherwise. */ + static constexpr bool is_const = Const; +}; /*! @brief Primary template isn't defined on purpose. */ template struct meta_function_descriptor; +/** + * @brief Meta function descriptor. + * @tparam Type Reflected type to which the meta function is associated. + * @tparam Ret Function return type. + * @tparam Class Actual owner of the member function. + * @tparam Args Function arguments. + */ +template +struct meta_function_descriptor + : meta_function_descriptor_traits< + Ret, + std::conditional_t, type_list, type_list>, + !std::is_base_of_v, + true> {}; /** * @brief Meta function descriptor. @@ -29,59 +60,54 @@ struct meta_function_descriptor; * @tparam Args Function arguments. */ template -struct meta_function_descriptor { - /*! @brief Meta function return type. */ - using return_type = Ret; - /*! @brief Meta function arguments. */ - using args_type = std::conditional_t, type_list, type_list>; - - /*! @brief True if the meta function is const, false otherwise. */ - static constexpr auto is_const = true; - /*! @brief True if the meta function is static, false otherwise. */ - static constexpr auto is_static = !std::is_same_v; -}; +struct meta_function_descriptor + : meta_function_descriptor_traits< + Ret, + std::conditional_t, type_list, type_list>, + !std::is_base_of_v, + false> {}; +/** + * @brief Meta function descriptor. + * @tparam Type Reflected type to which the meta data is associated. + * @tparam Class Actual owner of the data member. + * @tparam Ret Data member type. + */ +template +struct meta_function_descriptor + : meta_function_descriptor_traits< + Ret &, + std::conditional_t, type_list<>, type_list>, + !std::is_base_of_v, + false> {}; /** * @brief Meta function descriptor. * @tparam Type Reflected type to which the meta function is associated. * @tparam Ret Function return type. - * @tparam Class Actual owner of the member function. - * @tparam Args Function arguments. + * @tparam MaybeType First function argument. + * @tparam Args Other function arguments. */ -template -struct meta_function_descriptor { - /*! @brief Meta function return type. */ - using return_type = Ret; - /*! @brief Meta function arguments. */ - using args_type = std::conditional_t, type_list, type_list>; - - /*! @brief True if the meta function is const, false otherwise. */ - static constexpr auto is_const = false; - /*! @brief True if the meta function is static, false otherwise. */ - static constexpr auto is_static = !std::is_same_v; -}; - +template +struct meta_function_descriptor + : meta_function_descriptor_traits< + Ret, + std::conditional_t>, Type>, type_list, type_list>, + !std::is_base_of_v>, Type>, + std::is_base_of_v>, Type> && std::is_const_v>> {}; /** * @brief Meta function descriptor. * @tparam Type Reflected type to which the meta function is associated. * @tparam Ret Function return type. - * @tparam Args Function arguments. */ -template -struct meta_function_descriptor { - /*! @brief Meta function return type. */ - using return_type = Ret; - /*! @brief Meta function arguments. */ - using args_type = type_list; - - /*! @brief True if the meta function is const, false otherwise. */ - static constexpr auto is_const = false; - /*! @brief True if the meta function is static, false otherwise. */ - static constexpr auto is_static = true; -}; - +template +struct meta_function_descriptor + : meta_function_descriptor_traits< + Ret, + type_list<>, + true, + false> {}; /** * @brief Meta function helper. @@ -95,20 +121,25 @@ struct meta_function_descriptor { template class meta_function_helper { template - static constexpr meta_function_descriptor get_rid_of_noexcept(Ret(Class:: *)(Args...) const); + static constexpr meta_function_descriptor get_rid_of_noexcept(Ret (Class::*)(Args...) const); template - static constexpr meta_function_descriptor get_rid_of_noexcept(Ret(Class:: *)(Args...)); + static constexpr meta_function_descriptor get_rid_of_noexcept(Ret (Class::*)(Args...)); + + template + static constexpr meta_function_descriptor get_rid_of_noexcept(Ret Class::*); template - static constexpr meta_function_descriptor get_rid_of_noexcept(Ret(*)(Args...)); + static constexpr meta_function_descriptor get_rid_of_noexcept(Ret (*)(Args...)); + + template + static constexpr meta_function_descriptor get_rid_of_noexcept(Class); public: /*! @brief The meta function descriptor of the given function. */ using type = decltype(get_rid_of_noexcept(std::declval())); }; - /** * @brief Helper type. * @tparam Type Reflected type to which the meta function is associated. @@ -117,36 +148,69 @@ public: template using meta_function_helper_t = typename meta_function_helper::type; +/** + * @brief Wraps a value depending on the given policy. + * + * This function always returns a wrapped value in the requested context.
+ * Therefore, if the passed value is itself a wrapped object with a different + * context, it undergoes a rebinding to the requested context. + * + * @tparam Policy Optional policy (no policy set by default). + * @tparam Type Type of value to wrap. + * @param ctx The context from which to search for meta types. + * @param value Value to wrap. + * @return A meta any containing the returned value, if any. + */ +template +std::enable_if_t, meta_any> meta_dispatch(const meta_ctx &ctx, [[maybe_unused]] Type &&value) { + if constexpr(std::is_same_v) { + return meta_any{ctx, std::in_place_type}; + } else if constexpr(std::is_same_v) { + return meta_any{ctx, std::in_place_type, value}; + } else if constexpr(std::is_same_v) { + static_assert(std::is_lvalue_reference_v, "Invalid type"); + return meta_any{ctx, std::in_place_type &>, std::as_const(value)}; + } else { + return meta_any{ctx, std::forward(value)}; + } +} + +/** + * @brief Wraps a value depending on the given policy. + * @tparam Policy Optional policy (no policy set by default). + * @tparam Type Type of value to wrap. + * @param value Value to wrap. + * @return A meta any containing the returned value, if any. + */ +template +std::enable_if_t, meta_any> meta_dispatch(Type &&value) { + return meta_dispatch(locator::value_or(), std::forward(value)); +} /** * @brief Returns the meta type of the i-th element of a list of arguments. - * @tparam Args Actual types of arguments. + * @tparam Type Type list of the actual types of arguments. + * @param ctx The context from which to search for meta types. + * @param index The index of the element for which to return the meta type. * @return The meta type of the i-th element of the list of arguments. */ -template -[[nodiscard]] static meta_type meta_arg(type_list, const std::size_t index) ENTT_NOEXCEPT { - return internal::meta_arg_node(type_list{}, index); +template +[[nodiscard]] static meta_type meta_arg(const meta_ctx &ctx, const std::size_t index) noexcept { + auto &&context = internal::meta_context::from(ctx); + return {ctx, internal::meta_arg_node(context, Type{}, index)}; } - /** - * @brief Constructs an instance given a list of erased parameters, if possible. - * @tparam Type Actual type of the instance to construct. - * @tparam Args Types of arguments expected. - * @tparam Index Indexes to use to extract erased arguments from their list. - * @param args Parameters to use to construct the instance. - * @return A meta any containing the new instance, if any. + * @brief Returns the meta type of the i-th element of a list of arguments. + * @tparam Type Type list of the actual types of arguments. + * @param index The index of the element for which to return the meta type. + * @return The meta type of the i-th element of the list of arguments. */ -template -[[nodiscard]] meta_any meta_construct(meta_any * const args, std::index_sequence) { - if(((args+Index)->allow_cast() && ...)) { - return Type{(args+Index)->cast()...}; - } - - return {}; +template +[[nodiscard]] static meta_type meta_arg(const std::size_t index) noexcept { + return meta_arg(locator::value_or(), index); } - /** * @brief Sets the value of a given variable. * @tparam Type Reflected type to which the variable is associated. @@ -158,26 +222,20 @@ template template [[nodiscard]] bool meta_setter([[maybe_unused]] meta_handle instance, [[maybe_unused]] meta_any value) { if constexpr(!std::is_same_v && !std::is_same_v) { - if constexpr(std::is_function_v>>) { - using data_type = type_list_element_t<1u, typename meta_function_helper_t::args_type>; + if constexpr(std::is_member_function_pointer_v || std::is_function_v>>) { + using descriptor = meta_function_helper_t; + using data_type = type_list_element_t; - if(auto * const clazz = instance->try_cast(); clazz && value.allow_cast()) { - Data(*clazz, value.cast()); - return true; - } - } else if constexpr(std::is_member_function_pointer_v) { - using data_type = type_list_element_t<0u, typename meta_function_helper_t::args_type>; - - if(auto * const clazz = instance->try_cast(); clazz && value.allow_cast()) { - (clazz->*Data)(value.cast()); + if(auto *const clazz = instance->try_cast(); clazz && value.allow_cast()) { + std::invoke(Data, *clazz, value.cast()); return true; } } else if constexpr(std::is_member_object_pointer_v) { - using data_type = std::remove_reference_t().*Data)>; + using data_type = std::remove_reference_t::return_type>; if constexpr(!std::is_array_v && !std::is_const_v) { - if(auto * const clazz = instance->try_cast(); clazz && value.allow_cast()) { - clazz->*Data = value.cast(); + if(auto *const clazz = instance->try_cast(); clazz && value.allow_cast()) { + std::invoke(Data, *clazz) = value.cast(); return true; } } @@ -196,30 +254,49 @@ template return false; } - /** - * @brief Wraps a value depending on the given policy. + * @brief Gets the value of a given variable. + * + * @warning + * The context provided is used only for the return type.
+ * It's up to the caller to bind the arguments to the right context(s). + * + * @tparam Type Reflected type to which the variable is associated. + * @tparam Data The actual variable to get. * @tparam Policy Optional policy (no policy set by default). - * @tparam Type Type of value to wrap. - * @param value Value to wrap. - * @return A meta any containing the returned value. + * @param ctx The context from which to search for meta types. + * @param instance An opaque instance of the underlying type, if required. + * @return A meta any containing the value of the underlying variable. */ -template -meta_any meta_dispatch(Type &&value) { - if constexpr(std::is_same_v) { - return meta_any{std::in_place_type, std::forward(value)}; - } else if constexpr(std::is_same_v) { - return meta_any{std::in_place_type, std::forward(value)}; - } else if constexpr(std::is_same_v) { - static_assert(std::is_lvalue_reference_v, "Invalid type"); - return meta_any{std::in_place_type &>, std::as_const(value)}; +template +[[nodiscard]] std::enable_if_t, meta_any> meta_getter(const meta_ctx &ctx, [[maybe_unused]] meta_handle instance) { + if constexpr(std::is_member_pointer_v || std::is_function_v>>) { + if constexpr(!std::is_array_v>>>) { + if constexpr(std::is_invocable_v) { + if(auto *clazz = instance->try_cast(); clazz) { + return meta_dispatch(ctx, std::invoke(Data, *clazz)); + } + } + + if constexpr(std::is_invocable_v) { + if(auto *fallback = instance->try_cast(); fallback) { + return meta_dispatch(ctx, std::invoke(Data, *fallback)); + } + } + } + + return meta_any{meta_ctx_arg, ctx}; + } else if constexpr(std::is_pointer_v) { + if constexpr(std::is_array_v>) { + return meta_any{meta_ctx_arg, ctx}; + } else { + return meta_dispatch(ctx, *Data); + } } else { - static_assert(std::is_same_v, "Policy not supported"); - return meta_any{std::forward(value)}; + return meta_dispatch(ctx, Data); } } - /** * @brief Gets the value of a given variable. * @tparam Type Reflected type to which the variable is associated. @@ -229,105 +306,234 @@ meta_any meta_dispatch(Type &&value) { * @return A meta any containing the value of the underlying variable. */ template -[[nodiscard]] meta_any meta_getter([[maybe_unused]] meta_handle instance) { - if constexpr(std::is_function_v>>) { - auto * const clazz = instance->try_cast, const Type, Type>>(); - return clazz ? meta_dispatch(Data(*clazz)) : meta_any{}; - } else if constexpr(std::is_member_function_pointer_v) { - auto * const clazz = instance->try_cast, const Type, Type>>(); - return clazz ? meta_dispatch((clazz->*Data)()) : meta_any{}; - } else if constexpr(std::is_member_object_pointer_v) { - if constexpr(!std::is_array_v().*Data)>>>) { - if(auto * clazz = instance->try_cast(); clazz) { - return meta_dispatch(clazz->*Data); - } else if(auto * fallback = instance->try_cast(); fallback) { - return meta_dispatch(fallback->*Data); - } - } +[[nodiscard]] std::enable_if_t, meta_any> meta_getter(meta_handle instance) { + return meta_getter(locator::value_or(), std::move(instance)); +} - return meta_any{}; - } else if constexpr(std::is_pointer_v) { - if constexpr(std::is_array_v>) { - return meta_any{}; - } else { - return meta_dispatch(*Data); - } +/** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + +namespace internal { + +template +[[nodiscard]] meta_any meta_invoke_with_args(const meta_ctx &ctx, Candidate &&candidate, Args &&...args) { + if constexpr(std::is_same_v(candidate), args...)), void>) { + std::invoke(std::forward(candidate), args...); + return meta_any{ctx, std::in_place_type}; } else { - return meta_dispatch(Data); + return meta_dispatch(ctx, std::invoke(std::forward(candidate), args...)); } } +template +[[nodiscard]] meta_any meta_invoke(const meta_ctx &ctx, [[maybe_unused]] meta_handle instance, Candidate &&candidate, [[maybe_unused]] meta_any *args, std::index_sequence) { + using descriptor = meta_function_helper_t>; + + if constexpr(std::is_invocable_v, const Type &, type_list_element_t...>) { + if(const auto *const clazz = instance->try_cast(); clazz && ((args + Index)->allow_cast>() && ...)) { + return meta_invoke_with_args(ctx, std::forward(candidate), *clazz, (args + Index)->cast>()...); + } + } else if constexpr(std::is_invocable_v, Type &, type_list_element_t...>) { + if(auto *const clazz = instance->try_cast(); clazz && ((args + Index)->allow_cast>() && ...)) { + return meta_invoke_with_args(ctx, std::forward(candidate), *clazz, (args + Index)->cast>()...); + } + } else { + if(((args + Index)->allow_cast>() && ...)) { + return meta_invoke_with_args(ctx, std::forward(candidate), (args + Index)->cast>()...); + } + } + + return meta_any{meta_ctx_arg, ctx}; +} + +template +[[nodiscard]] meta_any meta_construct(const meta_ctx &ctx, meta_any *const args, std::index_sequence) { + if(((args + Index)->allow_cast() && ...)) { + return meta_any{ctx, std::in_place_type, (args + Index)->cast()...}; + } + + return meta_any{meta_ctx_arg, ctx}; +} + +} // namespace internal /** - * @brief Invokes a function given a list of erased parameters, if possible. + * Internal details not to be documented. + * @endcond + */ + +/** + * @brief Tries to _invoke_ an object given a list of erased parameters. + * + * @warning + * The context provided is used only for the return type.
+ * It's up to the caller to bind the arguments to the right context(s). + * + * @tparam Type Reflected type to which the object to _invoke_ is associated. + * @tparam Policy Optional policy (no policy set by default). + * @param ctx The context from which to search for meta types. + * @tparam Candidate The type of the actual object to _invoke_. + * @param instance An opaque instance of the underlying type, if required. + * @param candidate The actual object to _invoke_. + * @param args Parameters to use to _invoke_ the object. + * @return A meta any containing the returned value, if any. + */ +template +[[nodiscard]] std::enable_if_t, meta_any> meta_invoke(const meta_ctx &ctx, meta_handle instance, Candidate &&candidate, meta_any *const args) { + return internal::meta_invoke(ctx, std::move(instance), std::forward(candidate), args, std::make_index_sequence>::args_type::size>{}); +} + +/** + * @brief Tries to _invoke_ an object given a list of erased parameters. + * @tparam Type Reflected type to which the object to _invoke_ is associated. + * @tparam Policy Optional policy (no policy set by default). + * @tparam Candidate The type of the actual object to _invoke_. + * @param instance An opaque instance of the underlying type, if required. + * @param candidate The actual object to _invoke_. + * @param args Parameters to use to _invoke_ the object. + * @return A meta any containing the returned value, if any. + */ +template +[[nodiscard]] std::enable_if_t, meta_any> meta_invoke(meta_handle instance, Candidate &&candidate, meta_any *const args) { + return meta_invoke(locator::value_or(), std::move(instance), std::forward(candidate), args); +} + +/** + * @brief Tries to invoke a function given a list of erased parameters. + * + * @warning + * The context provided is used only for the return type.
+ * It's up to the caller to bind the arguments to the right context(s). + * * @tparam Type Reflected type to which the function is associated. * @tparam Candidate The actual function to invoke. * @tparam Policy Optional policy (no policy set by default). - * @tparam Index Indexes to use to extract erased arguments from their list. + * @param ctx The context from which to search for meta types. * @param instance An opaque instance of the underlying type, if required. * @param args Parameters to use to invoke the function. * @return A meta any containing the returned value, if any. */ -template -[[nodiscard]] std::enable_if_t, meta_any> meta_invoke([[maybe_unused]] meta_handle instance, meta_any *args, std::index_sequence) { - using descriptor = meta_function_helper_t; - - const auto invoke = [](auto &&maybe_clazz, auto &&... other) { - if constexpr(std::is_member_function_pointer_v) { - if constexpr(std::is_void_v) { - (std::forward(maybe_clazz).*Candidate)(std::forward(other)...); - return meta_any{std::in_place_type}; - } else { - return meta_dispatch((std::forward(maybe_clazz).*Candidate)(std::forward(other)...)); - } - } else { - if constexpr(std::is_void_v) { - Candidate(std::forward(maybe_clazz), std::forward(other)...); - return meta_any{std::in_place_type}; - } else { - return meta_dispatch(Candidate(std::forward(maybe_clazz), std::forward(other)...)); - } - } - }; - - if constexpr(std::is_invocable_v...>) { - if(const auto * const clazz = instance->try_cast(); clazz && ((args+Index)->allow_cast>() && ...)) { - return invoke(*clazz, (args+Index)->cast>()...); - } - } else if constexpr(std::is_invocable_v...>) { - if(auto * const clazz = instance->try_cast(); clazz && ((args+Index)->allow_cast>() && ...)) { - return invoke(*clazz, (args+Index)->cast>()...); - } - } else { - if(((args+Index)->allow_cast>() && ...)) { - return invoke((args+Index)->cast>()...); - } - } - - return meta_any{}; +template +[[nodiscard]] std::enable_if_t, meta_any> meta_invoke(const meta_ctx &ctx, meta_handle instance, meta_any *const args) { + return internal::meta_invoke(ctx, std::move(instance), Candidate, args, std::make_index_sequence>::args_type::size>{}); } - /** - * @brief Invokes a function given a list of erased parameters, if possible. + * @brief Tries to invoke a function given a list of erased parameters. * @tparam Type Reflected type to which the function is associated. * @tparam Candidate The actual function to invoke. * @tparam Policy Optional policy (no policy set by default). - * @tparam Index Indexes to use to extract erased arguments from their list. + * @param instance An opaque instance of the underlying type, if required. + * @param args Parameters to use to invoke the function. * @return A meta any containing the returned value, if any. */ -template -[[nodiscard]] std::enable_if_t, meta_any> meta_invoke(meta_handle, meta_any *, std::index_sequence) { - if constexpr(std::is_void_v) { - Candidate(); - return meta_any{std::in_place_type}; +template +[[nodiscard]] std::enable_if_t, meta_any> meta_invoke(meta_handle instance, meta_any *const args) { + return meta_invoke(locator::value_or(), std::move(instance), args); +} + +/** + * @brief Tries to construct an instance given a list of erased parameters. + * + * @warning + * The context provided is used only for the return type.
+ * It's up to the caller to bind the arguments to the right context(s). + * + * @tparam Type Actual type of the instance to construct. + * @tparam Args Types of arguments expected. + * @param ctx The context from which to search for meta types. + * @param args Parameters to use to construct the instance. + * @return A meta any containing the new instance, if any. + */ +template +[[nodiscard]] meta_any meta_construct(const meta_ctx &ctx, meta_any *const args) { + return internal::meta_construct(ctx, args, std::index_sequence_for{}); +} + +/** + * @brief Tries to construct an instance given a list of erased parameters. + * @tparam Type Actual type of the instance to construct. + * @tparam Args Types of arguments expected. + * @param args Parameters to use to construct the instance. + * @return A meta any containing the new instance, if any. + */ +template +[[nodiscard]] meta_any meta_construct(meta_any *const args) { + return meta_construct(locator::value_or(), args); +} + +/** + * @brief Tries to construct an instance given a list of erased parameters. + * + * @warning + * The context provided is used only for the return type.
+ * It's up to the caller to bind the arguments to the right context(s). + * + * @tparam Type Reflected type to which the object to _invoke_ is associated. + * @tparam Policy Optional policy (no policy set by default). + * @tparam Candidate The type of the actual object to _invoke_. + * @param ctx The context from which to search for meta types. + * @param candidate The actual object to _invoke_. + * @param args Parameters to use to _invoke_ the object. + * @return A meta any containing the returned value, if any. + */ +template +[[nodiscard]] meta_any meta_construct(const meta_ctx &ctx, Candidate &&candidate, meta_any *const args) { + if constexpr(meta_function_helper_t::is_static || std::is_class_v>>) { + return internal::meta_invoke(ctx, {}, std::forward(candidate), args, std::make_index_sequence>::args_type::size>{}); } else { - return meta_dispatch(Candidate()); + return internal::meta_invoke(ctx, *args, std::forward(candidate), args + 1u, std::make_index_sequence>::args_type::size>{}); } } - +/** + * @brief Tries to construct an instance given a list of erased parameters. + * @tparam Type Reflected type to which the object to _invoke_ is associated. + * @tparam Policy Optional policy (no policy set by default). + * @tparam Candidate The type of the actual object to _invoke_. + * @param candidate The actual object to _invoke_. + * @param args Parameters to use to _invoke_ the object. + * @return A meta any containing the returned value, if any. + */ +template +[[nodiscard]] std::enable_if_t, meta_any> meta_construct(Candidate &&candidate, meta_any *const args) { + return meta_construct(locator::value_or(), std::forward(candidate), args); } +/** + * @brief Tries to construct an instance given a list of erased parameters. + * + * @warning + * The context provided is used only for the return type.
+ * It's up to the caller to bind the arguments to the right context(s). + * + * @tparam Type Reflected type to which the function is associated. + * @tparam Candidate The actual function to invoke. + * @tparam Policy Optional policy (no policy set by default). + * @param ctx The context from which to search for meta types. + * @param args Parameters to use to invoke the function. + * @return A meta any containing the returned value, if any. + */ +template +[[nodiscard]] std::enable_if_t, meta_any> meta_construct(const meta_ctx &ctx, meta_any *const args) { + return meta_construct(ctx, Candidate, args); +} + +/** + * @brief Tries to construct an instance given a list of erased parameters. + * @tparam Type Reflected type to which the function is associated. + * @tparam Candidate The actual function to invoke. + * @tparam Policy Optional policy (no policy set by default). + * @param args Parameters to use to invoke the function. + * @return A meta any containing the returned value, if any. + */ +template +[[nodiscard]] std::enable_if_t, meta_any> meta_construct(meta_any *const args) { + return meta_construct(locator::value_or(), args); +} + +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/platform/android-ndk-r17.hpp b/LiteLoader/third-party/include/entt/platform/android-ndk-r17.hpp index 8527f3e..5696123 100644 --- a/LiteLoader/third-party/include/entt/platform/android-ndk-r17.hpp +++ b/LiteLoader/third-party/include/entt/platform/android-ndk-r17.hpp @@ -1,37 +1,29 @@ #ifndef ENTT_PLATFORM_ANDROID_NDK_R17_HPP #define ENTT_PLATFORM_ANDROID_NDK_R17_HPP - /** * @cond TURN_OFF_DOXYGEN * Internal details not to be documented. */ - #ifdef __ANDROID__ -#include -#if __NDK_MAJOR__ == 17 - - -#include -#include -#include +# include +# if __NDK_MAJOR__ == 17 +# include +# include +# include namespace std { - namespace internal { - template constexpr auto is_invocable(int) -> decltype(std::invoke(std::declval(), std::declval()...), std::true_type{}); - template constexpr std::false_type is_invocable(...); - template constexpr auto is_invocable_r(int) -> std::enable_if_t(), std::declval()...)), Ret>, std::true_type>; @@ -40,47 +32,36 @@ constexpr auto is_invocable_r(int) template constexpr std::false_type is_invocable_r(...); - -} - +} // namespace internal template struct is_invocable: decltype(internal::is_invocable(0)) {}; - template inline constexpr bool is_invocable_v = std::is_invocable::value; - template struct is_invocable_r: decltype(internal::is_invocable_r(0)) {}; - template inline constexpr bool is_invocable_r_v = std::is_invocable_r::value; - -template +template struct invoke_result { using type = decltype(std::invoke(std::declval(), std::declval()...)); }; - template using invoke_result_t = typename std::invoke_result::type; +} // namespace std -} - - +# endif #endif -#endif - /** * Internal details not to be documented. * @endcond */ - #endif diff --git a/LiteLoader/third-party/include/entt/poly/fwd.hpp b/LiteLoader/third-party/include/entt/poly/fwd.hpp index 32023e2..f24cdf2 100644 --- a/LiteLoader/third-party/include/entt/poly/fwd.hpp +++ b/LiteLoader/third-party/include/entt/poly/fwd.hpp @@ -1,26 +1,20 @@ #ifndef ENTT_POLY_FWD_HPP #define ENTT_POLY_FWD_HPP - -#include - +#include namespace entt { - -template)> +template class basic_poly; - /** * @brief Alias declaration for the most common use case. * @tparam Concept Concept descriptor. */ template -using poly = basic_poly; - - -} +using poly = basic_poly; +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/poly/poly.hpp b/LiteLoader/third-party/include/entt/poly/poly.hpp index 335324a..f10419e 100644 --- a/LiteLoader/third-party/include/entt/poly/poly.hpp +++ b/LiteLoader/third-party/include/entt/poly/poly.hpp @@ -1,29 +1,25 @@ #ifndef ENTT_POLY_POLY_HPP #define ENTT_POLY_POLY_HPP - #include #include #include #include #include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/any.hpp" -#include "third-party/include/entt/core/type_info.hpp" -#include "third-party/include/entt/core/type_traits.hpp" +#include "../core/any.hpp" +#include "../core/type_info.hpp" +#include "../core/type_traits.hpp" #include "fwd.hpp" - namespace entt { - /*! @brief Inspector class used to infer the type of the virtual table. */ struct poly_inspector { /** * @brief Generic conversion operator (definition only). * @tparam Type Type to which conversion is requested. */ - template + template operator Type &&() const; /** @@ -33,15 +29,14 @@ struct poly_inspector { * @param args The arguments to pass to the function. * @return A poly inspector convertible to any type. */ - template - poly_inspector invoke(Args &&... args) const; + template + poly_inspector invoke(Args &&...args) const; /*! @copydoc invoke */ - template - poly_inspector invoke(Args &&... args); + template + poly_inspector invoke(Args &&...args); }; - /** * @brief Static virtual table factory. * @tparam Concept Concept descriptor. @@ -53,35 +48,35 @@ class poly_vtable { using inspector = typename Concept::template type; template - static auto vtable_entry(Ret(*)(inspector &, Args...)) -> Ret(*)(basic_any &, Args...); + static auto vtable_entry(Ret (*)(inspector &, Args...)) -> Ret (*)(basic_any &, Args...); template - static auto vtable_entry(Ret(*)(const inspector &, Args...)) -> Ret(*)(const basic_any &, Args...); + static auto vtable_entry(Ret (*)(const inspector &, Args...)) -> Ret (*)(const basic_any &, Args...); template - static auto vtable_entry(Ret(*)(Args...)) -> Ret(*)(const basic_any &, Args...); + static auto vtable_entry(Ret (*)(Args...)) -> Ret (*)(const basic_any &, Args...); template - static auto vtable_entry(Ret(inspector:: *)(Args...)) -> Ret(*)(basic_any &, Args...); + static auto vtable_entry(Ret (inspector::*)(Args...)) -> Ret (*)(basic_any &, Args...); template - static auto vtable_entry(Ret(inspector:: *)(Args...) const) -> Ret(*)(const basic_any &, Args...); + static auto vtable_entry(Ret (inspector::*)(Args...) const) -> Ret (*)(const basic_any &, Args...); template - static auto make_vtable(value_list) - -> decltype(std::make_tuple(vtable_entry(Candidate)...)); + static auto make_vtable(value_list) noexcept + -> decltype(std::make_tuple(vtable_entry(Candidate)...)); template - [[nodiscard]] static constexpr auto make_vtable(type_list) { - if constexpr(sizeof...(Func) == 0) { + [[nodiscard]] static constexpr auto make_vtable(type_list) noexcept { + if constexpr(sizeof...(Func) == 0u) { return decltype(make_vtable(typename Concept::template impl{})){}; } else if constexpr((std::is_function_v && ...)) { - return decltype(std::make_tuple(vtable_entry(std::declval())...)){}; + return decltype(std::make_tuple(vtable_entry(std::declval())...)){}; } } template - static void fill_vtable_entry(Ret(* &entry)(Any &, Args...)) { + static void fill_vtable_entry(Ret (*&entry)(Any &, Args...)) noexcept { if constexpr(std::is_invocable_r_v) { entry = +[](Any &, Args... args) -> Ret { return std::invoke(Candidate, std::forward(args)...); @@ -94,15 +89,18 @@ class poly_vtable { } template - [[nodiscard]] static auto fill_vtable(std::index_sequence) { - type impl{}; + [[nodiscard]] static auto fill_vtable(std::index_sequence) noexcept { + vtable_type impl{}; (fill_vtable_entry>>(std::get(impl)), ...); return impl; } + using vtable_type = decltype(make_vtable(Concept{})); + static constexpr bool is_mono_v = std::tuple_size_v == 1u; + public: /*! @brief Virtual table type. */ - using type = decltype(make_vtable(Concept{})); + using type = std::conditional_t, const vtable_type *>; /** * @brief Returns a static virtual table for a specific concept and type. @@ -110,14 +108,18 @@ public: * @return A static virtual table for the given concept and type. */ template - [[nodiscard]] static const auto * instance() { + [[nodiscard]] static type instance() noexcept { static_assert(std::is_same_v>, "Type differs from its decayed form"); - static const auto vtable = fill_vtable(std::make_index_sequence::size>{}); - return &vtable; + static const vtable_type vtable = fill_vtable(std::make_index_sequence::size>{}); + + if constexpr(is_mono_v) { + return std::get<0>(vtable); + } else { + return &vtable; + } } }; - /** * @brief Poly base class used to inject functionalities into concepts. * @tparam Poly The outermost poly class. @@ -132,21 +134,31 @@ struct poly_base { * @param args The arguments to pass to the function. * @return The return value of the invoked function, if any. */ - template - [[nodiscard]] decltype(auto) invoke(const poly_base &self, Args &&... args) const { + template + [[nodiscard]] decltype(auto) invoke(const poly_base &self, Args &&...args) const { const auto &poly = static_cast(self); - return std::get(*poly.vtable)(poly.storage, std::forward(args)...); + + if constexpr(std::is_function_v>) { + return poly.vtable(poly.storage, std::forward(args)...); + } else { + return std::get(*poly.vtable)(poly.storage, std::forward(args)...); + } } /*! @copydoc invoke */ - template - [[nodiscard]] decltype(auto) invoke(poly_base &self, Args &&... args) { + template + [[nodiscard]] decltype(auto) invoke(poly_base &self, Args &&...args) { auto &poly = static_cast(self); - return std::get(*poly.vtable)(poly.storage, std::forward(args)...); + + if constexpr(std::is_function_v>) { + static_assert(Member == 0u, "Unknown member"); + return poly.vtable(poly.storage, std::forward(args)...); + } else { + return std::get(*poly.vtable)(poly.storage, std::forward(args)...); + } } }; - /** * @brief Shortcut for calling `poly_base::invoke`. * @tparam Member Index of the function to invoke. @@ -156,12 +168,11 @@ struct poly_base { * @param args The arguments to pass to the function. * @return The return value of the invoked function, if any. */ -template -decltype(auto) poly_call(Poly &&self, Args &&... args) { +template +decltype(auto) poly_call(Poly &&self, Args &&...args) { return std::forward(self).template invoke(self, std::forward(args)...); } - /** * @brief Static polymorphism made simple and within everyone's reach. * @@ -182,17 +193,16 @@ class basic_poly: private Concept::template type; - using vtable_type = typename poly_vtable::type; - public: /*! @brief Concept type. */ using concept_type = typename Concept::template type>; + /*! @brief Virtual table type. */ + using vtable_type = typename poly_vtable::type; /*! @brief Default constructor. */ - basic_poly() ENTT_NOEXCEPT + basic_poly() noexcept : storage{}, - vtable{} - {} + vtable{} {} /** * @brief Constructs a poly by directly initializing the new object. @@ -201,10 +211,9 @@ public: * @param args Parameters to use to construct the instance. */ template - explicit basic_poly(std::in_place_type_t, Args &&... args) + explicit basic_poly(std::in_place_type_t, Args &&...args) : storage{std::in_place_type, std::forward(args)...}, - vtable{poly_vtable::template instance>>()} - {} + vtable{poly_vtable::template instance>>()} {} /** * @brief Constructs a poly from a given value. @@ -212,41 +221,14 @@ public: * @param value An instance of an object to use to initialize the poly. */ template>, basic_poly>>> - basic_poly(Type &&value) ENTT_NOEXCEPT - : basic_poly{std::in_place_type>>, std::forward(value)} - {} + basic_poly(Type &&value) noexcept + : basic_poly{std::in_place_type>>, std::forward(value)} {} /** - * @brief Copy constructor. - * @param other The instance to copy from. + * @brief Returns the object type if any, `type_id()` otherwise. + * @return The object type if any, `type_id()` otherwise. */ - basic_poly(const basic_poly &other) = default; - - /** - * @brief Move constructor. - * @param other The instance to move from. - */ - basic_poly(basic_poly &&other) ENTT_NOEXCEPT - : basic_poly{} - { - swap(*this, other); - } - - /** - * @brief Assignment operator. - * @param other The instance to assign from. - * @return This poly object. - */ - basic_poly & operator=(basic_poly other) { - swap(other, *this); - return *this; - } - - /** - * @brief Returns the type of the contained object. - * @return The type of the contained object, if any. - */ - [[nodiscard]] type_info type() const ENTT_NOEXCEPT { + [[nodiscard]] const type_info &type() const noexcept { return storage.type(); } @@ -254,12 +236,12 @@ public: * @brief Returns an opaque pointer to the contained instance. * @return An opaque pointer the contained instance, if any. */ - [[nodiscard]] const void * data() const ENTT_NOEXCEPT { + [[nodiscard]] const void *data() const noexcept { return storage.data(); } /*! @copydoc data */ - [[nodiscard]] void * data() ENTT_NOEXCEPT { + [[nodiscard]] void *data() noexcept { return storage.data(); } @@ -270,59 +252,51 @@ public: * @param args Parameters to use to construct the instance. */ template - void emplace(Args &&... args) { - *this = basic_poly{std::in_place_type, std::forward(args)...}; + void emplace(Args &&...args) { + storage.template emplace(std::forward(args)...); + vtable = poly_vtable::template instance>>(); } /*! @brief Destroys contained object */ void reset() { - *this = basic_poly{}; + storage.reset(); + vtable = {}; } /** * @brief Returns false if a poly is empty, true otherwise. * @return False if the poly is empty, true otherwise. */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { - return !(vtable == nullptr); + [[nodiscard]] explicit operator bool() const noexcept { + return static_cast(storage); } /** * @brief Returns a pointer to the underlying concept. * @return A pointer to the underlying concept. */ - [[nodiscard]] concept_type * operator->() ENTT_NOEXCEPT { + [[nodiscard]] concept_type *operator->() noexcept { return this; } /*! @copydoc operator-> */ - [[nodiscard]] const concept_type * operator->() const ENTT_NOEXCEPT { + [[nodiscard]] const concept_type *operator->() const noexcept { return this; } - /** - * @brief Swaps two poly objects. - * @param lhs A valid poly object. - * @param rhs A valid poly object. - */ - friend void swap(basic_poly &lhs, basic_poly &rhs) { - using std::swap; - swap(lhs.storage, rhs.storage); - swap(lhs.vtable, rhs.vtable); - } - /** * @brief Aliasing constructor. * @return A poly that shares a reference to an unmanaged object. */ - [[nodiscard]] basic_poly as_ref() ENTT_NOEXCEPT { - basic_poly ref = std::as_const(*this).as_ref(); + [[nodiscard]] basic_poly as_ref() noexcept { + basic_poly ref{}; ref.storage = storage.as_ref(); + ref.vtable = vtable; return ref; } /*! @copydoc as_ref */ - [[nodiscard]] basic_poly as_ref() const ENTT_NOEXCEPT { + [[nodiscard]] basic_poly as_ref() const noexcept { basic_poly ref{}; ref.storage = storage.as_ref(); ref.vtable = vtable; @@ -331,11 +305,9 @@ public: private: basic_any storage; - const vtable_type *vtable; + vtable_type vtable; }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/process/process.hpp b/LiteLoader/third-party/include/entt/process/process.hpp index 9d6af69..b0d3a86 100644 --- a/LiteLoader/third-party/include/entt/process/process.hpp +++ b/LiteLoader/third-party/include/entt/process/process.hpp @@ -1,15 +1,12 @@ #ifndef ENTT_PROCESS_PROCESS_HPP #define ENTT_PROCESS_PROCESS_HPP - -#include +#include #include -#include "third-party/include/entt/config/config.h" - +#include namespace entt { - /** * @brief Base class for processes. * @@ -71,48 +68,48 @@ namespace entt { */ template class process { - enum class state: unsigned int { - UNINITIALIZED = 0, - RUNNING, - PAUSED, - SUCCEEDED, - FAILED, - ABORTED, - FINISHED, - REJECTED + enum class state : std::uint8_t { + uninitialized = 0, + running, + paused, + succeeded, + failed, + aborted, + finished, + rejected }; template - auto next(std::integral_constant) - -> decltype(std::declval().init(), void()) { + auto next(std::integral_constant) + -> decltype(std::declval().init(), void()) { static_cast(this)->init(); } template - auto next(std::integral_constant, Delta delta, void *data) - -> decltype(std::declval().update(delta, data), void()) { + auto next(std::integral_constant, Delta delta, void *data) + -> decltype(std::declval().update(delta, data), void()) { static_cast(this)->update(delta, data); } template - auto next(std::integral_constant) - -> decltype(std::declval().succeeded(), void()) { + auto next(std::integral_constant) + -> decltype(std::declval().succeeded(), void()) { static_cast(this)->succeeded(); } template - auto next(std::integral_constant) - -> decltype(std::declval().failed(), void()) { + auto next(std::integral_constant) + -> decltype(std::declval().failed(), void()) { static_cast(this)->failed(); } template - auto next(std::integral_constant) - -> decltype(std::declval().aborted(), void()) { + auto next(std::integral_constant) + -> decltype(std::declval().aborted(), void()) { static_cast(this)->aborted(); } - void next(...) const ENTT_NOEXCEPT {} + void next(...) const noexcept {} protected: /** @@ -121,9 +118,9 @@ protected: * The function is idempotent and it does nothing if the process isn't * alive. */ - void succeed() ENTT_NOEXCEPT { + void succeed() noexcept { if(alive()) { - current = state::SUCCEEDED; + current = state::succeeded; } } @@ -133,9 +130,9 @@ protected: * The function is idempotent and it does nothing if the process isn't * alive. */ - void fail() ENTT_NOEXCEPT { + void fail() noexcept { if(alive()) { - current = state::FAILED; + current = state::failed; } } @@ -145,9 +142,9 @@ protected: * The function is idempotent and it does nothing if the process isn't * running. */ - void pause() ENTT_NOEXCEPT { - if(current == state::RUNNING) { - current = state::PAUSED; + void pause() noexcept { + if(current == state::running) { + current = state::paused; } } @@ -157,9 +154,9 @@ protected: * The function is idempotent and it does nothing if the process isn't * paused. */ - void unpause() ENTT_NOEXCEPT { - if(current == state::PAUSED) { - current = state::RUNNING; + void unpause() noexcept { + if(current == state::paused) { + current = state::running; } } @@ -168,7 +165,7 @@ public: using delta_type = Delta; /*! @brief Default destructor. */ - virtual ~process() { + virtual ~process() noexcept { static_assert(std::is_base_of_v, "Incorrect use of the class template"); } @@ -182,7 +179,7 @@ public: */ void abort(const bool immediately = false) { if(alive()) { - current = state::ABORTED; + current = state::aborted; if(immediately) { tick({}); @@ -194,32 +191,32 @@ public: * @brief Returns true if a process is either running or paused. * @return True if the process is still alive, false otherwise. */ - [[nodiscard]] bool alive() const ENTT_NOEXCEPT { - return current == state::RUNNING || current == state::PAUSED; + [[nodiscard]] bool alive() const noexcept { + return current == state::running || current == state::paused; } /** * @brief Returns true if a process is already terminated. * @return True if the process is terminated, false otherwise. */ - [[nodiscard]] bool finished() const ENTT_NOEXCEPT { - return current == state::FINISHED; + [[nodiscard]] bool finished() const noexcept { + return current == state::finished; } /** * @brief Returns true if a process is currently paused. * @return True if the process is paused, false otherwise. */ - [[nodiscard]] bool paused() const ENTT_NOEXCEPT { - return current == state::PAUSED; + [[nodiscard]] bool paused() const noexcept { + return current == state::paused; } /** * @brief Returns true if a process terminated with errors. * @return True if the process terminated with errors, false otherwise. */ - [[nodiscard]] bool rejected() const ENTT_NOEXCEPT { - return current == state::REJECTED; + [[nodiscard]] bool rejected() const noexcept { + return current == state::rejected; } /** @@ -228,13 +225,13 @@ public: * @param data Optional data. */ void tick(const Delta delta, void *data = nullptr) { - switch (current) { - case state::UNINITIALIZED: - next(std::integral_constant{}); - current = state::RUNNING; + switch(current) { + case state::uninitialized: + next(std::integral_constant{}); + current = state::running; break; - case state::RUNNING: - next(std::integral_constant{}, delta, data); + case state::running: + next(std::integral_constant{}, delta, data); break; default: // suppress warnings @@ -243,17 +240,17 @@ public: // if it's dead, it must be notified and removed immediately switch(current) { - case state::SUCCEEDED: - next(std::integral_constant{}); - current = state::FINISHED; + case state::succeeded: + next(std::integral_constant{}); + current = state::finished; break; - case state::FAILED: - next(std::integral_constant{}); - current = state::REJECTED; + case state::failed: + next(std::integral_constant{}); + current = state::rejected; break; - case state::ABORTED: - next(std::integral_constant{}); - current = state::REJECTED; + case state::aborted: + next(std::integral_constant{}); + current = state::rejected; break; default: // suppress warnings @@ -262,10 +259,9 @@ public: } private: - state current{state::UNINITIALIZED}; + state current{state::uninitialized}; }; - /** * @brief Adaptor for lambdas and functors to turn them into processes. * @@ -313,9 +309,8 @@ struct process_adaptor: process, Delta>, private Fu * @param args Parameters to use to initialize the actual process. */ template - process_adaptor(Args &&... args) - : Func{std::forward(args)...} - {} + process_adaptor(Args &&...args) + : Func{std::forward(args)...} {} /** * @brief Updates a process and its internal state if required. @@ -323,12 +318,14 @@ struct process_adaptor: process, Delta>, private Fu * @param data Optional data. */ void update(const Delta delta, void *data) { - Func::operator()(delta, data, [this]() { this->succeed(); }, [this]() { this->fail(); }); + Func::operator()( + delta, + data, + [this]() { this->succeed(); }, + [this]() { this->fail(); }); } }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/process/scheduler.hpp b/LiteLoader/third-party/include/entt/process/scheduler.hpp index 7da7db6..23c7642 100644 --- a/LiteLoader/third-party/include/entt/process/scheduler.hpp +++ b/LiteLoader/third-party/include/entt/process/scheduler.hpp @@ -1,19 +1,16 @@ #ifndef ENTT_PROCESS_SCHEDULER_HPP #define ENTT_PROCESS_SCHEDULER_HPP - -#include -#include -#include #include +#include +#include #include -#include "third-party/include/entt/config/config.h" +#include +#include #include "process.hpp" - namespace entt { - /** * @brief Cooperative scheduler for processes. * @@ -43,9 +40,9 @@ namespace entt { template class scheduler { struct process_handler { - using instance_type = std::unique_ptr; - using update_fn_type = bool(process_handler &, Delta, void *); - using abort_fn_type = void(process_handler &, bool); + using instance_type = std::unique_ptr; + using update_fn_type = bool(scheduler &, std::size_t, Delta, void *); + using abort_fn_type = void(scheduler &, std::size_t, bool); using next_type = std::unique_ptr; instance_type instance; @@ -55,12 +52,11 @@ class scheduler { }; struct continuation { - continuation(process_handler *ref) - : handler{ref} - {} + continuation(process_handler *ref) noexcept + : handler{ref} {} template - continuation then(Args &&... args) { + continuation then(Args &&...args) { static_assert(std::is_base_of_v, Proc>, "Invalid process type"); auto proc = typename process_handler::instance_type{new Proc{std::forward(args)...}, &scheduler::deleter}; handler->next.reset(new process_handler{std::move(proc), &scheduler::update, &scheduler::abort, nullptr}); @@ -78,17 +74,17 @@ class scheduler { }; template - [[nodiscard]] static bool update(process_handler &handler, const Delta delta, void *data) { - auto *process = static_cast(handler.instance.get()); + [[nodiscard]] static bool update(scheduler &owner, std::size_t pos, const Delta delta, void *data) { + auto *process = static_cast(owner.handlers[pos].instance.get()); process->tick(delta, data); if(process->rejected()) { return true; } else if(process->finished()) { - if(handler.next) { + if(auto &&handler = owner.handlers[pos]; handler.next) { handler = std::move(*handler.next); // forces the process to exit the uninitialized state - return handler.update(handler, {}, nullptr); + return handler.update(owner, pos, {}, nullptr); } return true; @@ -98,8 +94,8 @@ class scheduler { } template - static void abort(process_handler &handler, const bool immediately) { - static_cast(handler.instance.get())->abort(immediately); + static void abort(scheduler &owner, std::size_t pos, const bool immediately) { + static_cast(owner.handlers[pos].instance.get())->abort(immediately); } template @@ -112,19 +108,20 @@ public: using size_type = std::size_t; /*! @brief Default constructor. */ - scheduler() = default; + scheduler() + : handlers{} {} /*! @brief Default move constructor. */ scheduler(scheduler &&) = default; /*! @brief Default move assignment operator. @return This scheduler. */ - scheduler & operator=(scheduler &&) = default; + scheduler &operator=(scheduler &&) = default; /** * @brief Number of processes currently scheduled. * @return Number of processes currently scheduled. */ - [[nodiscard]] size_type size() const ENTT_NOEXCEPT { + [[nodiscard]] size_type size() const noexcept { return handlers.size(); } @@ -132,7 +129,7 @@ public: * @brief Returns true if at least a process is currently scheduled. * @return True if there are scheduled processes, false otherwise. */ - [[nodiscard]] bool empty() const ENTT_NOEXCEPT { + [[nodiscard]] bool empty() const noexcept { return handlers.empty(); } @@ -172,13 +169,13 @@ public: * @return An opaque object to use to concatenate processes. */ template - auto attach(Args &&... args) { + auto attach(Args &&...args) { static_assert(std::is_base_of_v, Proc>, "Invalid process type"); auto proc = typename process_handler::instance_type{new Proc{std::forward(args)...}, &scheduler::deleter}; - process_handler handler{std::move(proc), &scheduler::update, &scheduler::abort, nullptr}; + auto &&ref = handlers.emplace_back(process_handler{std::move(proc), &scheduler::update, &scheduler::abort, nullptr}); // forces the process to exit the uninitialized state - handler.update(handler, {}, nullptr); - return continuation{&handlers.emplace_back(std::move(handler))}; + ref.update(*this, handlers.size() - 1u, {}, nullptr); + return continuation{&handlers.back()}; } /** @@ -250,17 +247,14 @@ public: * @param data Optional data. */ void update(const Delta delta, void *data = nullptr) { - auto sz = handlers.size(); - for(auto pos = handlers.size(); pos; --pos) { - auto &handler = handlers[pos-1]; + const auto curr = pos - 1u; - if(const auto dead = handler.update(handler, delta, data); dead) { - std::swap(handler, handlers[--sz]); + if(const auto dead = handlers[curr].update(*this, curr, delta, data); dead) { + std::swap(handlers[curr], handlers.back()); + handlers.pop_back(); } } - - handlers.erase(handlers.begin() + sz, handlers.end()); } /** @@ -274,23 +268,16 @@ public: * @param immediately Requests an immediate operation. */ void abort(const bool immediately = false) { - decltype(handlers) exec; - exec.swap(handlers); - - for(auto &&handler: exec) { - handler.abort(handler, immediately); + for(auto pos = handlers.size(); pos; --pos) { + const auto curr = pos - 1u; + handlers[curr].abort(*this, curr, immediately); } - - std::move(handlers.begin(), handlers.end(), std::back_inserter(exec)); - handlers.swap(exec); } private: std::vector handlers{}; }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/resource/cache.hpp b/LiteLoader/third-party/include/entt/resource/cache.hpp index 51e2b20..8688685 100644 --- a/LiteLoader/third-party/include/entt/resource/cache.hpp +++ b/LiteLoader/third-party/include/entt/resource/cache.hpp @@ -1,168 +1,367 @@ -#ifndef ENTT_RESOURCE_CACHE_HPP -#define ENTT_RESOURCE_CACHE_HPP - +#ifndef ENTT_RESOURCE_RESOURCE_CACHE_HPP +#define ENTT_RESOURCE_RESOURCE_CACHE_HPP +#include +#include +#include +#include +#include #include -#include #include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/fwd.hpp" -#include "handle.hpp" -#include "loader.hpp" +#include "../container/dense_map.hpp" +#include "../core/compressed_pair.hpp" +#include "../core/fwd.hpp" +#include "../core/iterator.hpp" +#include "../core/utility.hpp" #include "fwd.hpp" - +#include "loader.hpp" +#include "resource.hpp" namespace entt { +/** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + +namespace internal { + +template +class resource_cache_iterator final { + template + friend class resource_cache_iterator; + +public: + using value_type = std::pair>; + using pointer = input_iterator_pointer; + using reference = value_type; + using difference_type = std::ptrdiff_t; + using iterator_category = std::input_iterator_tag; + + constexpr resource_cache_iterator() noexcept = default; + + constexpr resource_cache_iterator(const It iter) noexcept + : it{iter} {} + + template && std::is_constructible_v>> + constexpr resource_cache_iterator(const resource_cache_iterator, Other> &other) noexcept + : it{other.it} {} + + constexpr resource_cache_iterator &operator++() noexcept { + return ++it, *this; + } + + constexpr resource_cache_iterator operator++(int) noexcept { + resource_cache_iterator orig = *this; + return ++(*this), orig; + } + + constexpr resource_cache_iterator &operator--() noexcept { + return --it, *this; + } + + constexpr resource_cache_iterator operator--(int) noexcept { + resource_cache_iterator orig = *this; + return operator--(), orig; + } + + constexpr resource_cache_iterator &operator+=(const difference_type value) noexcept { + it += value; + return *this; + } + + constexpr resource_cache_iterator operator+(const difference_type value) const noexcept { + resource_cache_iterator copy = *this; + return (copy += value); + } + + constexpr resource_cache_iterator &operator-=(const difference_type value) noexcept { + return (*this += -value); + } + + constexpr resource_cache_iterator operator-(const difference_type value) const noexcept { + return (*this + -value); + } + + [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept { + return {it[value].first, resource{it[value].second}}; + } + + [[nodiscard]] constexpr reference operator*() const noexcept { + return (*this)[0]; + } + + [[nodiscard]] constexpr pointer operator->() const noexcept { + return operator*(); + } + + template + friend constexpr std::ptrdiff_t operator-(const resource_cache_iterator &, const resource_cache_iterator &) noexcept; + + template + friend constexpr bool operator==(const resource_cache_iterator &, const resource_cache_iterator &) noexcept; + + template + friend constexpr bool operator<(const resource_cache_iterator &, const resource_cache_iterator &) noexcept; + +private: + It it; +}; + +template +[[nodiscard]] constexpr std::ptrdiff_t operator-(const resource_cache_iterator &lhs, const resource_cache_iterator &rhs) noexcept { + return lhs.it - rhs.it; +} + +template +[[nodiscard]] constexpr bool operator==(const resource_cache_iterator &lhs, const resource_cache_iterator &rhs) noexcept { + return lhs.it == rhs.it; +} + +template +[[nodiscard]] constexpr bool operator!=(const resource_cache_iterator &lhs, const resource_cache_iterator &rhs) noexcept { + return !(lhs == rhs); +} + +template +[[nodiscard]] constexpr bool operator<(const resource_cache_iterator &lhs, const resource_cache_iterator &rhs) noexcept { + return lhs.it < rhs.it; +} + +template +[[nodiscard]] constexpr bool operator>(const resource_cache_iterator &lhs, const resource_cache_iterator &rhs) noexcept { + return rhs < lhs; +} + +template +[[nodiscard]] constexpr bool operator<=(const resource_cache_iterator &lhs, const resource_cache_iterator &rhs) noexcept { + return !(lhs > rhs); +} + +template +[[nodiscard]] constexpr bool operator>=(const resource_cache_iterator &lhs, const resource_cache_iterator &rhs) noexcept { + return !(lhs < rhs); +} + +} // namespace internal /** - * @brief Simple cache for resources of a given type. - * - * Minimal implementation of a cache for resources of a given type. It doesn't - * offer much functionalities but it's suitable for small or medium sized - * applications and can be freely inherited to add targeted functionalities for - * large sized applications. - * - * @tparam Resource Type of resources managed by a cache. + * Internal details not to be documented. + * @endcond */ -template -struct resource_cache { + +/** + * @brief Basic cache for resources of any type. + * @tparam Type Type of resources managed by a cache. + * @tparam Loader Type of loader used to create the resources. + * @tparam Allocator Type of allocator used to manage memory and elements. + */ +template +class resource_cache { + using alloc_traits = typename std::allocator_traits; + static_assert(std::is_same_v, "Invalid value type"); + using container_allocator = typename alloc_traits::template rebind_alloc>; + using container_type = dense_map, container_allocator>; + +public: + /*! @brief Resource type. */ + using value_type = Type; /*! @brief Unsigned integer type. */ using size_type = std::size_t; - /*! @brief Type of resources managed by a cache. */ - using resource_type = Resource; + /*! @brief Loader type. */ + using loader_type = Loader; + /*! @brief Allocator type. */ + using allocator_type = Allocator; + /*! @brief Input iterator type. */ + using iterator = internal::resource_cache_iterator; + /*! @brief Constant input iterator type. */ + using const_iterator = internal::resource_cache_iterator; /*! @brief Default constructor. */ - resource_cache() = default; + resource_cache() + : resource_cache{loader_type{}} {} + + /** + * @brief Constructs an empty cache with a given allocator. + * @param allocator The allocator to use. + */ + explicit resource_cache(const allocator_type &allocator) + : resource_cache{loader_type{}, allocator} {} + + /** + * @brief Constructs an empty cache with a given allocator and loader. + * @param callable The loader to use. + * @param allocator The allocator to use. + */ + explicit resource_cache(const loader_type &callable, const allocator_type &allocator = allocator_type{}) + : pool{container_type{allocator}, callable} {} + + /*! @brief Default copy constructor. */ + resource_cache(const resource_cache &) = default; + + /** + * @brief Allocator-extended copy constructor. + * @param other The instance to copy from. + * @param allocator The allocator to use. + */ + resource_cache(const resource_cache &other, const allocator_type &allocator) + : pool{std::piecewise_construct, std::forward_as_tuple(other.pool.first(), allocator), std::forward_as_tuple(other.pool.second())} {} /*! @brief Default move constructor. */ resource_cache(resource_cache &&) = default; - /*! @brief Default move assignment operator. @return This cache. */ - resource_cache & operator=(resource_cache &&) = default; + /** + * @brief Allocator-extended move constructor. + * @param other The instance to move from. + * @param allocator The allocator to use. + */ + resource_cache(resource_cache &&other, const allocator_type &allocator) + : pool{std::piecewise_construct, std::forward_as_tuple(std::move(other.pool.first()), allocator), std::forward_as_tuple(std::move(other.pool.second()))} {} /** - * @brief Number of resources managed by a cache. - * @return Number of resources currently stored. + * @brief Default copy assignment operator. + * @return This cache. */ - [[nodiscard]] size_type size() const ENTT_NOEXCEPT { - return resources.size(); + resource_cache &operator=(const resource_cache &) = default; + + /** + * @brief Default move assignment operator. + * @return This cache. + */ + resource_cache &operator=(resource_cache &&) = default; + + /** + * @brief Returns the associated allocator. + * @return The associated allocator. + */ + [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { + return pool.first().get_allocator(); + } + + /** + * @brief Returns an iterator to the beginning. + * + * The returned iterator points to the first instance of the cache. If the + * cache is empty, the returned iterator will be equal to `end()`. + * + * @return An iterator to the first instance of the internal cache. + */ + [[nodiscard]] const_iterator cbegin() const noexcept { + return pool.first().begin(); + } + + /*! @copydoc cbegin */ + [[nodiscard]] const_iterator begin() const noexcept { + return cbegin(); + } + + /*! @copydoc begin */ + [[nodiscard]] iterator begin() noexcept { + return pool.first().begin(); + } + + /** + * @brief Returns an iterator to the end. + * + * The returned iterator points to the element following the last instance + * of the cache. Attempting to dereference the returned iterator results in + * undefined behavior. + * + * @return An iterator to the element following the last instance of the + * internal cache. + */ + [[nodiscard]] const_iterator cend() const noexcept { + return pool.first().end(); + } + + /*! @copydoc cend */ + [[nodiscard]] const_iterator end() const noexcept { + return cend(); + } + + /*! @copydoc end */ + [[nodiscard]] iterator end() noexcept { + return pool.first().end(); } /** * @brief Returns true if a cache contains no resources, false otherwise. * @return True if the cache contains no resources, false otherwise. */ - [[nodiscard]] bool empty() const ENTT_NOEXCEPT { - return resources.empty(); + [[nodiscard]] bool empty() const noexcept { + return pool.first().empty(); } /** - * @brief Clears a cache and discards all its resources. - * - * Handles are not invalidated and the memory used by a resource isn't - * freed as long as at least a handle keeps the resource itself alive. + * @brief Number of resources managed by a cache. + * @return Number of resources currently stored. */ - void clear() ENTT_NOEXCEPT { - resources.clear(); + [[nodiscard]] size_type size() const noexcept { + return pool.first().size(); + } + + /*! @brief Clears a cache. */ + void clear() noexcept { + pool.first().clear(); } /** - * @brief Loads the resource that corresponds to a given identifier. + * @brief Loads a resource, if its identifier does not exist. * - * In case an identifier isn't already present in the cache, it loads its - * resource and stores it aside for future uses. Arguments are forwarded - * directly to the loader in order to construct properly the requested - * resource. - * - * @note - * If the identifier is already present in the cache, this function does - * nothing and the arguments are simply discarded. + * Arguments are forwarded directly to the loader and _consumed_ only if the + * resource doesn't already exist. * * @warning - * If the resource cannot be loaded correctly, the returned handle will be + * If the resource isn't loaded correctly, the returned handle could be * invalid and any use of it will result in undefined behavior. * - * @tparam Loader Type of loader to use to load the resource if required. * @tparam Args Types of arguments to use to load the resource if required. * @param id Unique resource identifier. * @param args Arguments to use to load the resource if required. + * @return A pair consisting of an iterator to the inserted element (or to + * the element that prevented the insertion) and a bool denoting whether the + * insertion took place. + */ + template + std::pair load(const id_type id, Args &&...args) { + if(auto it = pool.first().find(id); it != pool.first().end()) { + return {it, false}; + } + + return pool.first().emplace(id, pool.second()(std::forward(args)...)); + } + + /** + * @brief Force loads a resource, if its identifier does not exist. + * @copydetails load + */ + template + std::pair force_load(const id_type id, Args &&...args) { + return {pool.first().insert_or_assign(id, pool.second()(std::forward(args)...)).first, true}; + } + + /** + * @brief Returns a handle for a given resource identifier. + * + * @warning + * There is no guarantee that the returned handle is valid.
+ * If it is not, any use will result in indefinite behavior. + * + * @param id Unique resource identifier. * @return A handle for the given resource. */ - template - resource_handle load(const id_type id, Args &&... args) { - if(auto it = resources.find(id); it == resources.cend()) { - if(auto handle = temp(std::forward(args)...); handle) { - return (resources[id] = std::move(handle)); - } - } else { - return it->second; + [[nodiscard]] resource operator[](const id_type id) const { + if(auto it = pool.first().find(id); it != pool.first().cend()) { + return resource{it->second}; } return {}; } - /** - * @brief Reloads a resource or loads it for the first time if not present. - * - * Equivalent to the following snippet (pseudocode): - * - * @code{.cpp} - * cache.discard(id); - * cache.load(id, args...); - * @endcode - * - * Arguments are forwarded directly to the loader in order to construct - * properly the requested resource. - * - * @warning - * If the resource cannot be loaded correctly, the returned handle will be - * invalid and any use of it will result in undefined behavior. - * - * @tparam Loader Type of loader to use to load the resource. - * @tparam Args Types of arguments to use to load the resource. - * @param id Unique resource identifier. - * @param args Arguments to use to load the resource. - * @return A handle for the given resource. - */ - template - resource_handle reload(const id_type id, Args &&... args) { - return (discard(id), load(id, std::forward(args)...)); - } - - /** - * @brief Creates a temporary handle for a resource. - * - * Arguments are forwarded directly to the loader in order to construct - * properly the requested resource. The handle isn't stored aside and the - * cache isn't in charge of the lifetime of the resource itself. - * - * @tparam Loader Type of loader to use to load the resource. - * @tparam Args Types of arguments to use to load the resource. - * @param args Arguments to use to load the resource. - * @return A handle for the given resource. - */ - template - [[nodiscard]] resource_handle temp(Args &&... args) const { - return Loader{}.get(std::forward(args)...); - } - - /** - * @brief Creates a handle for a given resource identifier. - * - * A resource handle can be in a either valid or invalid state. In other - * terms, a resource handle is properly initialized with a resource if the - * cache contains the resource itself. Otherwise the returned handle is - * uninitialized and accessing it results in undefined behavior. - * - * @sa resource_handle - * - * @param id Unique resource identifier. - * @return A handle for the given resource. - */ - [[nodiscard]] resource_handle handle(const id_type id) const { - if(auto it = resources.find(id); it != resources.cend()) { - return it->second; + /*! @copydoc operator[] */ + [[nodiscard]] resource operator[](const id_type id) { + if(auto it = pool.first().find(id); it != pool.first().end()) { + return resource{it->second}; } return {}; @@ -174,64 +373,51 @@ struct resource_cache { * @return True if the cache contains the resource, false otherwise. */ [[nodiscard]] bool contains(const id_type id) const { - return (resources.find(id) != resources.cend()); + return pool.first().contains(id); } /** - * @brief Discards the resource that corresponds to a given identifier. - * - * Handles are not invalidated and the memory used by the resource isn't - * freed as long as at least a handle keeps the resource itself alive. - * + * @brief Removes an element from a given position. + * @param pos An iterator to the element to remove. + * @return An iterator following the removed element. + */ + iterator erase(const_iterator pos) { + const auto it = pool.first().begin(); + return pool.first().erase(it + (pos - const_iterator{it})); + } + + /** + * @brief Removes the given elements from a cache. + * @param first An iterator to the first element of the range of elements. + * @param last An iterator past the last element of the range of elements. + * @return An iterator following the last removed element. + */ + iterator erase(const_iterator first, const_iterator last) { + const auto it = pool.first().begin(); + return pool.first().erase(it + (first - const_iterator{it}), it + (last - const_iterator{it})); + } + + /** + * @brief Removes the given elements from a cache. * @param id Unique resource identifier. + * @return Number of resources erased (either 0 or 1). */ - void discard(const id_type id) { - if(auto it = resources.find(id); it != resources.end()) { - resources.erase(it); - } + size_type erase(const id_type id) { + return pool.first().erase(id); } /** - * @brief Iterates all resources. - * - * The function object is invoked for each element. It is provided with - * either the resource identifier, the resource handle or both of them.
- * The signature of the function must be equivalent to one of the following - * forms: - * - * @code{.cpp} - * void(const entt::id_type); - * void(entt::resource_handle); - * void(const entt::id_type, entt::resource_handle); - * @endcode - * - * @tparam Func Type of the function object to invoke. - * @param func A valid function object. + * @brief Returns the loader used to create resources. + * @return The loader used to create resources. */ - template - void each(Func func) const { - auto begin = resources.begin(); - auto end = resources.end(); - - while(begin != end) { - auto curr = begin++; - - if constexpr(std::is_invocable_v) { - func(curr->first); - } else if constexpr(std::is_invocable_v>) { - func(curr->second); - } else { - func(curr->first, curr->second); - } - } + [[nodiscard]] loader_type loader() const { + return pool.second(); } private: - std::unordered_map> resources; + compressed_pair pool; }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/resource/fwd.hpp b/LiteLoader/third-party/include/entt/resource/fwd.hpp index 8a2c9e9..ed63da5 100644 --- a/LiteLoader/third-party/include/entt/resource/fwd.hpp +++ b/LiteLoader/third-party/include/entt/resource/fwd.hpp @@ -1,23 +1,19 @@ #ifndef ENTT_RESOURCE_FWD_HPP #define ENTT_RESOURCE_FWD_HPP +#include namespace entt { +template +struct resource_loader; + +template, typename = std::allocator> +class resource_cache; template -struct resource_cache; - - -template -class resource_handle; - - -template -class resource_loader; - - -} +class resource; +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/resource/loader.hpp b/LiteLoader/third-party/include/entt/resource/loader.hpp index fa39d55..f59d748 100644 --- a/LiteLoader/third-party/include/entt/resource/loader.hpp +++ b/LiteLoader/third-party/include/entt/resource/loader.hpp @@ -1,66 +1,33 @@ #ifndef ENTT_RESOURCE_LOADER_HPP #define ENTT_RESOURCE_LOADER_HPP - +#include +#include #include "fwd.hpp" -#include "handle.hpp" - namespace entt { - /** - * @brief Base class for resource loaders. - * - * Resource loaders must inherit from this class and stay true to the CRTP - * idiom. Moreover, a resource loader must expose a public, const member - * function named `load` that accepts a variable number of arguments and returns - * a handle to the resource just created.
- * As an example: - * - * @code{.cpp} - * struct my_resource {}; - * - * struct my_loader: entt::resource_loader { - * resource_handle load(int value) const { - * // use the integer value somehow - * return std::make_shared(); - * } - * }; - * @endcode - * - * In general, resource loaders should not have a state or retain data of any - * type. They should let the cache manage their resources instead. - * - * @note - * Base class and CRTP idiom aren't strictly required with the current - * implementation. One could argue that a cache can easily work with loaders of - * any type. However, future changes won't be breaking ones by forcing the use - * of a base class today and that's why the model is already in its place. - * - * @tparam Loader Type of the derived class. - * @tparam Resource Type of resource for which to use the loader. + * @brief Transparent loader for shared resources. + * @tparam Type Type of resources created by the loader. */ -template -class resource_loader { - /*! @brief Resource loaders are friends of their caches. */ - template - friend struct resource_cache; +template +struct resource_loader { + /*! @brief Result type. */ + using result_type = std::shared_ptr; /** - * @brief Loads the resource and returns it. - * @tparam Args Types of arguments for the loader. - * @param args Arguments for the loader. - * @return The resource just loaded or an empty pointer in case of errors. + * @brief Constructs a shared pointer to a resource from its arguments. + * @tparam Args Types of arguments to use to construct the resource. + * @param args Parameters to use to construct the resource. + * @return A shared pointer to a resource of the given type. */ template - [[nodiscard]] resource_handle get(Args &&... args) const { - return static_cast(this)->load(std::forward(args)...); + result_type operator()(Args &&...args) const { + return std::make_shared(std::forward(args)...); } }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/signal/delegate.hpp b/LiteLoader/third-party/include/entt/signal/delegate.hpp index 88dd0bc..4419616 100644 --- a/LiteLoader/third-party/include/entt/signal/delegate.hpp +++ b/LiteLoader/third-party/include/entt/signal/delegate.hpp @@ -1,77 +1,54 @@ #ifndef ENTT_SIGNAL_DELEGATE_HPP #define ENTT_SIGNAL_DELEGATE_HPP - -#include #include -#include #include +#include #include -#include "third-party/include/entt/core/type_traits.hpp" -#include "third-party/include/entt/config/config.h" - +#include +#include "../config/config.h" +#include "../core/type_traits.hpp" +#include "fwd.hpp" namespace entt { - /** * @cond TURN_OFF_DOXYGEN * Internal details not to be documented. */ - namespace internal { - template -auto function_pointer(Ret(*)(Args...)) -> Ret(*)(Args...); - +constexpr auto function_pointer(Ret (*)(Args...)) -> Ret (*)(Args...); template -auto function_pointer(Ret(*)(Type, Args...), Other &&) -> Ret(*)(Args...); - +constexpr auto function_pointer(Ret (*)(Type, Args...), Other &&) -> Ret (*)(Args...); template -auto function_pointer(Ret(Class:: *)(Args...), Other &&...) -> Ret(*)(Args...); - +constexpr auto function_pointer(Ret (Class::*)(Args...), Other &&...) -> Ret (*)(Args...); template -auto function_pointer(Ret(Class:: *)(Args...) const, Other &&...) -> Ret(*)(Args...); - +constexpr auto function_pointer(Ret (Class::*)(Args...) const, Other &&...) -> Ret (*)(Args...); template -auto function_pointer(Type Class:: *, Other &&...) -> Type(*)(); - +constexpr auto function_pointer(Type Class::*, Other &&...) -> Type (*)(); template -using function_pointer_t = decltype(internal::function_pointer(std::declval()...)); - +using function_pointer_t = decltype(function_pointer(std::declval()...)); template -[[nodiscard]] constexpr auto index_sequence_for(Ret(*)(Args...)) { +[[nodiscard]] constexpr auto index_sequence_for(Ret (*)(Args...)) { return std::index_sequence_for{}; } - -} - +} // namespace internal /** * Internal details not to be documented. * @endcond */ - -/*! @brief Used to wrap a function or a member of a specified type. */ -template -struct connect_arg_t {}; - - -/*! @brief Constant of type connect_arg_t used to disambiguate calls. */ -template -inline constexpr connect_arg_t connect_arg{}; - - /** * @brief Basic delegate implementation. * @@ -81,7 +58,6 @@ inline constexpr connect_arg_t connect_arg{}; template class delegate; - /** * @brief Utility class to use to send around functions and members. * @@ -97,7 +73,7 @@ class delegate; template class delegate { template - [[nodiscard]] auto wrap(std::index_sequence) ENTT_NOEXCEPT { + [[nodiscard]] auto wrap(std::index_sequence) noexcept { return [](const void *, Args... args) -> Ret { [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward(args)...); return static_cast(std::invoke(Candidate, std::forward>>(std::get(arguments))...)); @@ -105,7 +81,7 @@ class delegate { } template - [[nodiscard]] auto wrap(Type &, std::index_sequence) ENTT_NOEXCEPT { + [[nodiscard]] auto wrap(Type &, std::index_sequence) noexcept { return [](const void *payload, Args... args) -> Ret { [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward(args)...); Type *curr = static_cast(const_cast *>(payload)); @@ -114,7 +90,7 @@ class delegate { } template - [[nodiscard]] auto wrap(Type *, std::index_sequence) ENTT_NOEXCEPT { + [[nodiscard]] auto wrap(Type *, std::index_sequence) noexcept { return [](const void *payload, Args... args) -> Ret { [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward(args)...); Type *curr = static_cast(const_cast *>(payload)); @@ -131,30 +107,19 @@ public: using result_type = Ret; /*! @brief Default constructor. */ - delegate() ENTT_NOEXCEPT - : fn{nullptr}, data{nullptr} - {} + delegate() noexcept + : instance{nullptr}, + fn{nullptr} {} /** - * @brief Constructs a delegate and connects a free function or an unbound - * member. + * @brief Constructs a delegate with a given object or payload, if any. * @tparam Candidate Function or member to connect to the delegate. + * @tparam Type Type of class or type of payload, if any. + * @param value_or_instance Optional valid object that fits the purpose. */ - template - delegate(connect_arg_t) ENTT_NOEXCEPT { - connect(); - } - - /** - * @brief Constructs a delegate and connects a free function with payload or - * a bound member. - * @tparam Candidate Function or member to connect to the delegate. - * @tparam Type Type of class or type of payload. - * @param value_or_instance A valid object that fits the purpose. - */ - template - delegate(connect_arg_t, Type &&value_or_instance) ENTT_NOEXCEPT { - connect(std::forward(value_or_instance)); + template + delegate(connect_arg_t, Type &&...value_or_instance) noexcept { + connect(std::forward(value_or_instance)...); } /** @@ -163,7 +128,7 @@ public: * @param function Function to connect to the delegate. * @param payload User defined arbitrary data. */ - delegate(function_type *function, const void *payload = nullptr) ENTT_NOEXCEPT { + delegate(function_type *function, const void *payload = nullptr) noexcept { connect(function, payload); } @@ -172,8 +137,8 @@ public: * @tparam Candidate Function or member to connect to the delegate. */ template - void connect() ENTT_NOEXCEPT { - data = nullptr; + void connect() noexcept { + instance = nullptr; if constexpr(std::is_invocable_r_v) { fn = [](const void *, Args... args) -> Ret { @@ -202,8 +167,8 @@ public: * @param value_or_instance A valid reference that fits the purpose. */ template - void connect(Type &value_or_instance) ENTT_NOEXCEPT { - data = &value_or_instance; + void connect(Type &value_or_instance) noexcept { + instance = &value_or_instance; if constexpr(std::is_invocable_r_v) { fn = [](const void *payload, Args... args) -> Ret { @@ -226,8 +191,8 @@ public: * @param value_or_instance A valid pointer that fits the purpose. */ template - void connect(Type *value_or_instance) ENTT_NOEXCEPT { - data = value_or_instance; + void connect(Type *value_or_instance) noexcept { + instance = value_or_instance; if constexpr(std::is_invocable_r_v) { fn = [](const void *payload, Args... args) -> Ret { @@ -252,9 +217,10 @@ public: * @param function Function to connect to the delegate. * @param payload User defined arbitrary data. */ - void connect(function_type *function, const void *payload = nullptr) ENTT_NOEXCEPT { + void connect(function_type *function, const void *payload = nullptr) noexcept { + ENTT_ASSERT(function != nullptr, "Uninitialized function pointer"); + instance = payload; fn = function; - data = payload; } /** @@ -262,17 +228,17 @@ public: * * After a reset, a delegate cannot be invoked anymore. */ - void reset() ENTT_NOEXCEPT { + void reset() noexcept { + instance = nullptr; fn = nullptr; - data = nullptr; } /** * @brief Returns the instance or the payload linked to a delegate, if any. * @return An opaque pointer to the underlying data. */ - [[nodiscard]] const void * instance() const ENTT_NOEXCEPT { - return data; + [[nodiscard]] const void *data() const noexcept { + return instance; } /** @@ -289,15 +255,15 @@ public: */ Ret operator()(Args... args) const { ENTT_ASSERT(static_cast(*this), "Uninitialized delegate"); - return fn(data, std::forward(args)...); + return fn(instance, std::forward(args)...); } /** * @brief Checks whether a delegate actually stores a listener. * @return False if the delegate is empty, true otherwise. */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { - // no need to test also data + [[nodiscard]] explicit operator bool() const noexcept { + // no need to also test instance return !(fn == nullptr); } @@ -306,16 +272,15 @@ public: * @param other Delegate with which to compare. * @return False if the two contents differ, true otherwise. */ - [[nodiscard]] bool operator==(const delegate &other) const ENTT_NOEXCEPT { - return fn == other.fn && data == other.data; + [[nodiscard]] bool operator==(const delegate &other) const noexcept { + return fn == other.fn && instance == other.instance; } private: + const void *instance; function_type *fn; - const void *data; }; - /** * @brief Compares the contents of two delegates. * @tparam Ret Return type of a function type. @@ -325,19 +290,16 @@ private: * @return True if the two contents differ, false otherwise. */ template -[[nodiscard]] bool operator!=(const delegate &lhs, const delegate &rhs) ENTT_NOEXCEPT { +[[nodiscard]] bool operator!=(const delegate &lhs, const delegate &rhs) noexcept { return !(lhs == rhs); } - /** * @brief Deduction guide. * @tparam Candidate Function or member to connect to the delegate. */ template -delegate(connect_arg_t) --> delegate>>; - +delegate(connect_arg_t) -> delegate>>; /** * @brief Deduction guide. @@ -345,9 +307,7 @@ delegate(connect_arg_t) * @tparam Type Type of class or type of payload. */ template -delegate(connect_arg_t, Type &&) --> delegate>>; - +delegate(connect_arg_t, Type &&) -> delegate>>; /** * @brief Deduction guide. @@ -355,11 +315,8 @@ delegate(connect_arg_t, Type &&) * @tparam Args Types of arguments of a function type. */ template -delegate(Ret(*)(const void *, Args...), const void * = nullptr) --> delegate; - - -} +delegate(Ret (*)(const void *, Args...), const void * = nullptr) -> delegate; +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/signal/dispatcher.hpp b/LiteLoader/third-party/include/entt/signal/dispatcher.hpp index 25a04e2..72c5694 100644 --- a/LiteLoader/third-party/include/entt/signal/dispatcher.hpp +++ b/LiteLoader/third-party/include/entt/signal/dispatcher.hpp @@ -1,20 +1,102 @@ #ifndef ENTT_SIGNAL_DISPATCHER_HPP #define ENTT_SIGNAL_DISPATCHER_HPP - #include +#include #include #include #include #include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/fwd.hpp" -#include "third-party/include/entt/core/type_info.hpp" +#include "../container/dense_map.hpp" +#include "../core/compressed_pair.hpp" +#include "../core/fwd.hpp" +#include "../core/type_info.hpp" +#include "../core/utility.hpp" +#include "fwd.hpp" #include "sigh.hpp" - namespace entt { +/** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + +namespace internal { + +struct basic_dispatcher_handler { + virtual ~basic_dispatcher_handler() = default; + virtual void publish() = 0; + virtual void disconnect(void *) = 0; + virtual void clear() noexcept = 0; + virtual std::size_t size() const noexcept = 0; +}; + +template +class dispatcher_handler final: public basic_dispatcher_handler { + static_assert(std::is_same_v>, "Invalid type"); + + using alloc_traits = std::allocator_traits; + using signal_type = sigh; + using container_type = std::vector>; + +public: + using allocator_type = Allocator; + + dispatcher_handler(const allocator_type &allocator) + : signal{allocator}, + events{allocator} {} + + void publish() override { + const auto length = events.size(); + + for(std::size_t pos{}; pos < length; ++pos) { + signal.publish(events[pos]); + } + + events.erase(events.cbegin(), events.cbegin() + length); + } + + void disconnect(void *instance) override { + bucket().disconnect(instance); + } + + void clear() noexcept override { + events.clear(); + } + + [[nodiscard]] auto bucket() noexcept { + return typename signal_type::sink_type{signal}; + } + + void trigger(Type event) { + signal.publish(event); + } + + template + void enqueue(Args &&...args) { + if constexpr(std::is_aggregate_v) { + events.push_back(Type{std::forward(args)...}); + } else { + events.emplace_back(std::forward(args)...); + } + } + + std::size_t size() const noexcept override { + return events.size(); + } + +private: + signal_type signal; + container_type events; +}; + +} // namespace internal + +/** + * Internal details not to be documented. + * @endcond + */ /** * @brief Basic dispatcher implementation. @@ -22,172 +104,223 @@ namespace entt { * A dispatcher can be used either to trigger an immediate event or to enqueue * events to be published all together once per tick.
* Listeners are provided in the form of member functions. For each event of - * type `Event`, listeners are such that they can be invoked with an argument of - * type `Event &`, no matter what the return type is. + * type `Type`, listeners are such that they can be invoked with an argument of + * type `Type &`, no matter what the return type is. * * The dispatcher creates instances of the `sigh` class internally. Refer to the * documentation of the latter for more details. + * + * @tparam Allocator Type of allocator used to manage memory and elements. */ -class dispatcher { - struct basic_pool { - virtual ~basic_pool() = default; - virtual void publish() = 0; - virtual void disconnect(void *) = 0; - virtual void clear() ENTT_NOEXCEPT = 0; - }; +template +class basic_dispatcher { + template + using handler_type = internal::dispatcher_handler; - template - struct pool_handler final: basic_pool { - static_assert(std::is_same_v>, "Invalid event type"); + using key_type = id_type; + // std::shared_ptr because of its type erased allocator which is useful here + using mapped_type = std::shared_ptr; - using signal_type = sigh; - using sink_type = typename signal_type::sink_type; + using alloc_traits = std::allocator_traits; + using container_allocator = typename alloc_traits::template rebind_alloc>; + using container_type = dense_map, container_allocator>; - void publish() override { - const auto length = events.size(); + template + [[nodiscard]] handler_type &assure(const id_type id) { + static_assert(std::is_same_v>, "Non-decayed types not allowed"); + auto &&ptr = pools.first()[id]; - for(std::size_t pos{}; pos < length; ++pos) { - signal.publish(events[pos]); - } - - events.erase(events.cbegin(), events.cbegin()+length); + if(!ptr) { + const auto &allocator = get_allocator(); + ptr = std::allocate_shared>(allocator, allocator); } - void disconnect(void *instance) override { - sink().disconnect(instance); + return static_cast &>(*ptr); + } + + template + [[nodiscard]] const handler_type *assure(const id_type id) const { + static_assert(std::is_same_v>, "Non-decayed types not allowed"); + + if(auto it = pools.first().find(id); it != pools.first().cend()) { + return static_cast *>(it->second.get()); } - void clear() ENTT_NOEXCEPT override { - events.clear(); - } - - [[nodiscard]] sink_type sink() ENTT_NOEXCEPT { - return entt::sink{signal}; - } - - template - void trigger(Args &&... args) { - Event instance{std::forward(args)...}; - signal.publish(instance); - } - - template - void enqueue(Args &&... args) { - if constexpr(std::is_aggregate_v) { - events.push_back(Event{std::forward(args)...}); - } else { - events.emplace_back(std::forward(args)...); - } - } - - private: - signal_type signal{}; - std::vector events; - }; - - template - [[nodiscard]] pool_handler & assure() { - const auto index = type_seq::value(); - - if(!(index < pools.size())) { - pools.resize(std::size_t(index)+1u); - } - - if(!pools[index]) { - pools[index].reset(new pool_handler{}); - } - - return static_cast &>(*pools[index]); + return nullptr; } public: + /*! @brief Allocator type. */ + using allocator_type = Allocator; + /*! @brief Unsigned integer type. */ + using size_type = std::size_t; + /*! @brief Default constructor. */ - dispatcher() = default; - - /*! @brief Default move constructor. */ - dispatcher(dispatcher &&) = default; - - /*! @brief Default move assignment operator. @return This dispatcher. */ - dispatcher & operator=(dispatcher &&) = default; + basic_dispatcher() + : basic_dispatcher{allocator_type{}} {} /** - * @brief Returns a sink object for the given event. + * @brief Constructs a dispatcher with a given allocator. + * @param allocator The allocator to use. + */ + explicit basic_dispatcher(const allocator_type &allocator) + : pools{allocator, allocator} {} + + /** + * @brief Move constructor. + * @param other The instance to move from. + */ + basic_dispatcher(basic_dispatcher &&other) noexcept + : pools{std::move(other.pools)} {} + + /** + * @brief Allocator-extended move constructor. + * @param other The instance to move from. + * @param allocator The allocator to use. + */ + basic_dispatcher(basic_dispatcher &&other, const allocator_type &allocator) noexcept + : pools{container_type{std::move(other.pools.first()), allocator}, allocator} {} + + /** + * @brief Move assignment operator. + * @param other The instance to move from. + * @return This dispatcher. + */ + basic_dispatcher &operator=(basic_dispatcher &&other) noexcept { + pools = std::move(other.pools); + return *this; + } + + /** + * @brief Exchanges the contents with those of a given dispatcher. + * @param other Dispatcher to exchange the content with. + */ + void swap(basic_dispatcher &other) { + using std::swap; + swap(pools, other.pools); + } + + /** + * @brief Returns the associated allocator. + * @return The associated allocator. + */ + [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { + return pools.second(); + } + + /** + * @brief Returns the number of pending events for a given type. + * @tparam Type Type of event for which to return the count. + * @param id Name used to map the event queue within the dispatcher. + * @return The number of pending events for the given type. + */ + template + size_type size(const id_type id = type_hash::value()) const noexcept { + const auto *cpool = assure>(id); + return cpool ? cpool->size() : 0u; + } + + /** + * @brief Returns the total number of pending events. + * @return The total number of pending events. + */ + size_type size() const noexcept { + size_type count{}; + + for(auto &&cpool: pools.first()) { + count += cpool.second->size(); + } + + return count; + } + + /** + * @brief Returns a sink object for the given event and queue. * * A sink is an opaque object used to connect listeners to events. * * The function type for a listener is _compatible_ with: + * * @code{.cpp} - * void(Event &); + * void(Type &); * @endcode * * The order of invocation of the listeners isn't guaranteed. * * @sa sink * - * @tparam Event Type of event of which to get the sink. + * @tparam Type Type of event of which to get the sink. + * @param id Name used to map the event queue within the dispatcher. * @return A temporary sink object. */ - template - [[nodiscard]] auto sink() { - return assure().sink(); + template + [[nodiscard]] auto sink(const id_type id = type_hash::value()) { + return assure(id).bucket(); } /** - * @brief Triggers an immediate event of the given type. - * - * All the listeners registered for the given type are immediately notified. - * The event is discarded after the execution. - * - * @tparam Event Type of event to trigger. - * @tparam Args Types of arguments to use to construct the event. - * @param args Arguments to use to construct the event. + * @brief Triggers an immediate event of a given type. + * @tparam Type Type of event to trigger. + * @param value An instance of the given type of event. */ - template - void trigger(Args &&... args) { - assure().trigger(std::forward(args)...); + template + void trigger(Type &&value = {}) { + trigger(type_hash>::value(), std::forward(value)); } /** - * @brief Triggers an immediate event of the given type. - * - * All the listeners registered for the given type are immediately notified. - * The event is discarded after the execution. - * - * @tparam Event Type of event to trigger. - * @param event An instance of the given type of event. + * @brief Triggers an immediate event on a queue of a given type. + * @tparam Type Type of event to trigger. + * @param value An instance of the given type of event. + * @param id Name used to map the event queue within the dispatcher. */ - template - void trigger(Event &&event) { - assure>().trigger(std::forward(event)); + template + void trigger(const id_type id, Type &&value = {}) { + assure>(id).trigger(std::forward(value)); } /** * @brief Enqueues an event of the given type. - * - * An event of the given type is queued. No listener is invoked. Use the - * `update` member function to notify listeners when ready. - * - * @tparam Event Type of event to enqueue. + * @tparam Type Type of event to enqueue. * @tparam Args Types of arguments to use to construct the event. * @param args Arguments to use to construct the event. */ - template - void enqueue(Args &&... args) { - assure().enqueue(std::forward(args)...); + template + void enqueue(Args &&...args) { + enqueue_hint(type_hash::value(), std::forward(args)...); } /** * @brief Enqueues an event of the given type. - * - * An event of the given type is queued. No listener is invoked. Use the - * `update` member function to notify listeners when ready. - * - * @tparam Event Type of event to enqueue. - * @param event An instance of the given type of event. + * @tparam Type Type of event to enqueue. + * @param value An instance of the given type of event. */ - template - void enqueue(Event &&event) { - assure>().enqueue(std::forward(event)); + template + void enqueue(Type &&value) { + enqueue_hint(type_hash>::value(), std::forward(value)); + } + + /** + * @brief Enqueues an event of the given type. + * @tparam Type Type of event to enqueue. + * @tparam Args Types of arguments to use to construct the event. + * @param id Name used to map the event queue within the dispatcher. + * @param args Arguments to use to construct the event. + */ + template + void enqueue_hint(const id_type id, Args &&...args) { + assure(id).enqueue(std::forward(args)...); + } + + /** + * @brief Enqueues an event of the given type. + * @tparam Type Type of event to enqueue. + * @param id Name used to map the event queue within the dispatcher. + * @param value An instance of the given type of event. + */ + template + void enqueue_hint(const id_type id, Type &&value) { + assure>(id).enqueue(std::forward(value)); } /** @@ -209,69 +342,49 @@ public: */ template void disconnect(Type *value_or_instance) { - for(auto &&cpool: pools) { - if(cpool) { - cpool->disconnect(value_or_instance); - } + for(auto &&cpool: pools.first()) { + cpool.second->disconnect(value_or_instance); } } /** - * @brief Discards all the events queued so far. - * - * If no types are provided, the dispatcher will clear all the existing - * pools. - * - * @tparam Event Type of events to discard. + * @brief Discards all the events stored so far in a given queue. + * @tparam Type Type of event to discard. + * @param id Name used to map the event queue within the dispatcher. */ - template - void clear() { - if constexpr(sizeof...(Event) == 0) { - for(auto &&cpool: pools) { - if(cpool) { - cpool->clear(); - } - } - } else { - (assure().clear(), ...); + template + void clear(const id_type id = type_hash::value()) { + assure(id).clear(); + } + + /*! @brief Discards all the events queued so far. */ + void clear() noexcept { + for(auto &&cpool: pools.first()) { + cpool.second->clear(); } } /** - * @brief Delivers all the pending events of the given type. - * - * This method is blocking and it doesn't return until all the events are - * delivered to the registered listeners. It's responsibility of the users - * to reduce at a minimum the time spent in the bodies of the listeners. - * - * @tparam Event Type of events to send. + * @brief Delivers all the pending events of a given queue. + * @tparam Type Type of event to send. + * @param id Name used to map the event queue within the dispatcher. */ - template - void update() { - assure().publish(); + template + void update(const id_type id = type_hash::value()) { + assure(id).publish(); } - /** - * @brief Delivers all the pending events. - * - * This method is blocking and it doesn't return until all the events are - * delivered to the registered listeners. It's responsibility of the users - * to reduce at a minimum the time spent in the bodies of the listeners. - */ + /*! @brief Delivers all the pending events. */ void update() const { - for(auto pos = pools.size(); pos; --pos) { - if(auto &&cpool = pools[pos-1]; cpool) { - cpool->publish(); - } + for(auto &&cpool: pools.first()) { + cpool.second->publish(); } } private: - std::vector> pools; + compressed_pair pools; }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/signal/emitter.hpp b/LiteLoader/third-party/include/entt/signal/emitter.hpp index 11144b3..263da18 100644 --- a/LiteLoader/third-party/include/entt/signal/emitter.hpp +++ b/LiteLoader/third-party/include/entt/signal/emitter.hpp @@ -1,28 +1,22 @@ #ifndef ENTT_SIGNAL_EMITTER_HPP #define ENTT_SIGNAL_EMITTER_HPP - -#include #include -#include -#include -#include #include #include -#include -#include "third-party/include/entt/config/config.h" -#include "third-party/include/entt/core/fwd.hpp" -#include "third-party/include/entt/core/type_info.hpp" - +#include "../container/dense_map.hpp" +#include "../core/compressed_pair.hpp" +#include "../core/fwd.hpp" +#include "../core/type_info.hpp" +#include "../core/utility.hpp" +#include "fwd.hpp" namespace entt { - /** * @brief General purpose event emitter. * - * The emitter class template follows the CRTP idiom. To create a custom emitter - * type, derived classes must inherit directly from the base class as: + * To create an emitter type, derived classes must inherit from the base as: * * @code{.cpp} * struct my_emitter: emitter { @@ -30,298 +24,147 @@ namespace entt { * } * @endcode * - * Pools for the type of events are created internally on the fly. It's not - * required to specify in advance the full list of accepted types.
- * Moreover, whenever an event is published, an emitter provides the listeners - * with a reference to itself along with a reference to the event. Therefore - * listeners have an handy way to work with it without incurring in the need of - * capturing a reference to the emitter. + * Handlers for the different events are created internally on the fly. It's not + * required to specify in advance the full list of accepted events.
+ * Moreover, whenever an event is published, an emitter also passes a reference + * to itself to its listeners. * - * @tparam Derived Actual type of emitter that extends the class template. + * @tparam Derived Emitter type. + * @tparam Allocator Type of allocator used to manage memory and elements. */ -template +template class emitter { - struct basic_pool { - virtual ~basic_pool() = default; - virtual bool empty() const ENTT_NOEXCEPT = 0; - virtual void clear() ENTT_NOEXCEPT = 0; - }; + using key_type = id_type; + using mapped_type = std::function; - template - struct pool_handler final: basic_pool { - static_assert(std::is_same_v>, "Invalid event type"); - - using listener_type = std::function; - using element_type = std::pair; - using container_type = std::list; - using connection_type = typename container_type::iterator; - - [[nodiscard]] bool empty() const ENTT_NOEXCEPT override { - auto pred = [](auto &&element) { return element.first; }; - - return std::all_of(once_list.cbegin(), once_list.cend(), pred) && - std::all_of(on_list.cbegin(), on_list.cend(), pred); - } - - void clear() ENTT_NOEXCEPT override { - if(publishing) { - for(auto &&element: once_list) { - element.first = true; - } - - for(auto &&element: on_list) { - element.first = true; - } - } else { - once_list.clear(); - on_list.clear(); - } - } - - connection_type once(listener_type listener) { - return once_list.emplace(once_list.cend(), false, std::move(listener)); - } - - connection_type on(listener_type listener) { - return on_list.emplace(on_list.cend(), false, std::move(listener)); - } - - void erase(connection_type conn) { - conn->first = true; - - if(!publishing) { - auto pred = [](auto &&element) { return element.first; }; - once_list.remove_if(pred); - on_list.remove_if(pred); - } - } - - void publish(Event &event, Derived &ref) { - container_type swap_list; - once_list.swap(swap_list); - - publishing = true; - - for(auto &&element: on_list) { - element.first ? void() : element.second(event, ref); - } - - for(auto &&element: swap_list) { - element.first ? void() : element.second(event, ref); - } - - publishing = false; - - on_list.remove_if([](auto &&element) { return element.first; }); - } - - private: - bool publishing{false}; - container_type once_list{}; - container_type on_list{}; - }; - - template - [[nodiscard]] pool_handler * assure() { - const auto index = type_seq::value(); - - if(!(index < pools.size())) { - pools.resize(std::size_t(index)+1u); - } - - if(!pools[index]) { - pools[index].reset(new pool_handler{}); - } - - return static_cast *>(pools[index].get()); - } - - template - [[nodiscard]] const pool_handler * assure() const { - const auto index = type_seq::value(); - return (!(index < pools.size()) || !pools[index]) ? nullptr : static_cast *>(pools[index].get()); - } + using alloc_traits = std::allocator_traits; + using container_allocator = typename alloc_traits::template rebind_alloc>; + using container_type = dense_map, container_allocator>; public: - /** @brief Type of listeners accepted for the given event. */ - template - using listener = typename pool_handler::listener_type; - - /** - * @brief Generic connection type for events. - * - * Type of the connection object returned by the event emitter whenever a - * listener for the given type is registered.
- * It can be used to break connections still in use. - * - * @tparam Event Type of event for which the connection is created. - */ - template - struct connection: private pool_handler::connection_type { - /** @brief Event emitters are friend classes of connections. */ - friend class emitter; - - /*! @brief Default constructor. */ - connection() = default; - - /** - * @brief Creates a connection that wraps its underlying instance. - * @param conn A connection object to wrap. - */ - connection(typename pool_handler::connection_type conn) - : pool_handler::connection_type{std::move(conn)} - {} - }; + /*! @brief Allocator type. */ + using allocator_type = Allocator; + /*! @brief Unsigned integer type. */ + using size_type = std::size_t; /*! @brief Default constructor. */ - emitter() = default; + emitter() + : emitter{allocator_type{}} {} + + /** + * @brief Constructs an emitter with a given allocator. + * @param allocator The allocator to use. + */ + explicit emitter(const allocator_type &allocator) + : handlers{allocator, allocator} {} /*! @brief Default destructor. */ - virtual ~emitter() { - static_assert(std::is_base_of_v, Derived>, "Incorrect use of the class template"); - } - - /*! @brief Default move constructor. */ - emitter(emitter &&) = default; - - /*! @brief Default move assignment operator. @return This emitter. */ - emitter & operator=(emitter &&) = default; - - /** - * @brief Emits the given event. - * - * All the listeners registered for the specific event type are invoked with - * the given event. The event type must either have a proper constructor for - * the arguments provided or be an aggregate type. - * - * @tparam Event Type of event to publish. - * @tparam Args Types of arguments to use to construct the event. - * @param args Parameters to use to initialize the event. - */ - template - void publish(Args &&... args) { - Event instance{std::forward(args)...}; - assure()->publish(instance, *static_cast(this)); + virtual ~emitter() noexcept { + static_assert(std::is_base_of_v, Derived>, "Invalid emitter type"); } /** - * @brief Registers a long-lived listener with the event emitter. - * - * This method can be used to register a listener designed to be invoked - * more than once for the given event type.
- * The connection returned by the method can be freely discarded. It's meant - * to be used later to disconnect the listener if required. - * - * The listener is as a callable object that can be moved and the type of - * which is _compatible_ with `void(Event &, Derived &)`. - * - * @note - * Whenever an event is emitted, the emitter provides the listener with a - * reference to the derived class. Listeners don't have to capture those - * instances for later uses. - * - * @tparam Event Type of event to which to connect the listener. - * @param instance The listener to register. - * @return Connection object that can be used to disconnect the listener. + * @brief Move constructor. + * @param other The instance to move from. */ - template - connection on(listener instance) { - return assure()->on(std::move(instance)); + emitter(emitter &&other) noexcept + : handlers{std::move(other.handlers)} {} + + /** + * @brief Allocator-extended move constructor. + * @param other The instance to move from. + * @param allocator The allocator to use. + */ + emitter(emitter &&other, const allocator_type &allocator) noexcept + : handlers{container_type{std::move(other.handlers.first()), allocator}, allocator} {} + + /** + * @brief Move assignment operator. + * @param other The instance to move from. + * @return This dispatcher. + */ + emitter &operator=(emitter &&other) noexcept { + handlers = std::move(other.handlers); + return *this; } /** - * @brief Registers a short-lived listener with the event emitter. - * - * This method can be used to register a listener designed to be invoked - * only once for the given event type.
- * The connection returned by the method can be freely discarded. It's meant - * to be used later to disconnect the listener if required. - * - * The listener is as a callable object that can be moved and the type of - * which is _compatible_ with `void(Event &, Derived &)`. - * - * @note - * Whenever an event is emitted, the emitter provides the listener with a - * reference to the derived class. Listeners don't have to capture those - * instances for later uses. - * - * @tparam Event Type of event to which to connect the listener. - * @param instance The listener to register. - * @return Connection object that can be used to disconnect the listener. + * @brief Exchanges the contents with those of a given emitter. + * @param other Emitter to exchange the content with. */ - template - connection once(listener instance) { - return assure()->once(std::move(instance)); + void swap(emitter &other) { + using std::swap; + swap(handlers, other.handlers); + } + + /** + * @brief Returns the associated allocator. + * @return The associated allocator. + */ + [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { + return handlers.second(); + } + + /** + * @brief Publishes a given event. + * @tparam Type Type of event to trigger. + * @param value An instance of the given type of event. + */ + template + void publish(Type &&value) { + if(const auto id = type_id().hash(); handlers.first().contains(id)) { + handlers.first()[id](&value); + } + } + + /** + * @brief Registers a listener with the event emitter. + * @tparam Type Type of event to which to connect the listener. + * @param func The listener to register. + */ + template + void on(std::function func) { + handlers.first().insert_or_assign(type_id().hash(), [func = std::move(func), this](void *value) { + func(*static_cast(value), static_cast(*this)); + }); } /** * @brief Disconnects a listener from the event emitter. - * - * Do not use twice the same connection to disconnect a listener, it results - * in undefined behavior. Once used, discard the connection object. - * - * @tparam Event Type of event of the connection. - * @param conn A valid connection. + * @tparam Type Type of event of the listener. */ - template - void erase(connection conn) { - assure()->erase(std::move(conn)); + template + void erase() { + handlers.first().erase(type_hash>>::value()); } - /** - * @brief Disconnects all the listeners for the given event type. - * - * All the connections previously returned for the given event are - * invalidated. Using them results in undefined behavior. - * - * @tparam Event Type of event to reset. - */ - template - void clear() { - assure()->clear(); - } - - /** - * @brief Disconnects all the listeners. - * - * All the connections previously returned are invalidated. Using them - * results in undefined behavior. - */ - void clear() ENTT_NOEXCEPT { - for(auto &&cpool: pools) { - if(cpool) { - cpool->clear(); - } - } + /*! @brief Disconnects all the listeners. */ + void clear() noexcept { + handlers.first().clear(); } /** * @brief Checks if there are listeners registered for the specific event. - * @tparam Event Type of event to test. + * @tparam Type Type of event to test. * @return True if there are no listeners registered, false otherwise. */ - template - [[nodiscard]] bool empty() const { - const auto *cpool = assure(); - return !cpool || cpool->empty(); + template + [[nodiscard]] bool contains() const { + return handlers.first().contains(type_hash>>::value()); } /** * @brief Checks if there are listeners registered with the event emitter. * @return True if there are no listeners registered, false otherwise. */ - [[nodiscard]] bool empty() const ENTT_NOEXCEPT { - return std::all_of(pools.cbegin(), pools.cend(), [](auto &&cpool) { - return !cpool || cpool->empty(); - }); + [[nodiscard]] bool empty() const noexcept { + return handlers.first().empty(); } private: - std::vector> pools{}; + compressed_pair handlers; }; - -} - +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/signal/fwd.hpp b/LiteLoader/third-party/include/entt/signal/fwd.hpp index 950a1d5..b0964b6 100644 --- a/LiteLoader/third-party/include/entt/signal/fwd.hpp +++ b/LiteLoader/third-party/include/entt/signal/fwd.hpp @@ -1,36 +1,46 @@ #ifndef ENTT_SIGNAL_FWD_HPP #define ENTT_SIGNAL_FWD_HPP +#include namespace entt { - template class delegate; +template> +class basic_dispatcher; -class dispatcher; - - -template +template> class emitter; - class connection; - struct scoped_connection; - template class sink; - -template +template> class sigh; +/*! @brief Alias declaration for the most common use case. */ +using dispatcher = basic_dispatcher<>; -} +/*! @brief Disambiguation tag for constructors and the like. */ +template +struct connect_arg_t { + /*! @brief Default constructor. */ + explicit connect_arg_t() = default; +}; +/** + * @brief Constant of type connect_arg_t used to disambiguate calls. + * @tparam Candidate Element to connect (likely a free or member function). + */ +template +inline constexpr connect_arg_t connect_arg{}; + +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/entt/signal/sigh.hpp b/LiteLoader/third-party/include/entt/signal/sigh.hpp index 0f4faf4..5e85354 100644 --- a/LiteLoader/third-party/include/entt/signal/sigh.hpp +++ b/LiteLoader/third-party/include/entt/signal/sigh.hpp @@ -1,45 +1,39 @@ #ifndef ENTT_SIGNAL_SIGH_HPP #define ENTT_SIGNAL_SIGH_HPP - -#include -#include -#include #include #include #include -#include "third-party/include/entt/config/config.h" +#include +#include #include "delegate.hpp" #include "fwd.hpp" - namespace entt { - /** * @brief Sink class. * * Primary template isn't defined on purpose. All the specializations give a * compile-time error unless the template parameter is a function type. * - * @tparam Function A valid function type. + * @tparam Type A valid signal handler type. */ -template +template class sink; - /** * @brief Unmanaged signal handler. * * Primary template isn't defined on purpose. All the specializations give a * compile-time error unless the template parameter is a function type. * - * @tparam Function A valid function type. + * @tparam Type A valid function type. + * @tparam Allocator Type of allocator used to manage memory and elements. */ -template +template class sigh; - /** * @brief Unmanaged signal handler. * @@ -54,30 +48,107 @@ class sigh; * * @tparam Ret Return type of a function type. * @tparam Args Types of arguments of a function type. + * @tparam Allocator Type of allocator used to manage memory and elements. */ -template -class sigh { +template +class sigh { /*! @brief A sink is allowed to modify a signal. */ - friend class sink; + friend class sink>; + + using alloc_traits = std::allocator_traits; + using container_type = std::vector, typename alloc_traits::template rebind_alloc>>; public: + /*! @brief Allocator type. */ + using allocator_type = Allocator; /*! @brief Unsigned integer type. */ using size_type = std::size_t; /*! @brief Sink type. */ - using sink_type = sink; + using sink_type = sink>; + + /*! @brief Default constructor. */ + sigh() noexcept(std::is_nothrow_default_constructible_v &&std::is_nothrow_constructible_v) + : sigh{allocator_type{}} {} /** - * @brief Instance type when it comes to connecting member functions. - * @tparam Class Type of class to which the member function belongs. + * @brief Constructs a signal handler with a given allocator. + * @param allocator The allocator to use. */ - template - using instance_type = Class *; + explicit sigh(const allocator_type &allocator) noexcept(std::is_nothrow_constructible_v) + : calls{allocator} {} + + /** + * @brief Copy constructor. + * @param other The instance to copy from. + */ + sigh(const sigh &other) noexcept(std::is_nothrow_copy_constructible_v) + : calls{other.calls} {} + + /** + * @brief Allocator-extended copy constructor. + * @param other The instance to copy from. + * @param allocator The allocator to use. + */ + sigh(const sigh &other, const allocator_type &allocator) noexcept(std::is_nothrow_constructible_v) + : calls{other.calls, allocator} {} + + /** + * @brief Move constructor. + * @param other The instance to move from. + */ + sigh(sigh &&other) noexcept(std::is_nothrow_move_constructible_v) + : calls{std::move(other.calls)} {} + + /** + * @brief Allocator-extended move constructor. + * @param other The instance to move from. + * @param allocator The allocator to use. + */ + sigh(sigh &&other, const allocator_type &allocator) noexcept(std::is_nothrow_constructible_v) + : calls{std::move(other.calls), allocator} {} + + /** + * @brief Copy assignment operator. + * @param other The instance to copy from. + * @return This signal handler. + */ + sigh &operator=(const sigh &other) noexcept(std::is_nothrow_copy_assignable_v) { + calls = other.calls; + return *this; + } + + /** + * @brief Move assignment operator. + * @param other The instance to move from. + * @return This signal handler. + */ + sigh &operator=(sigh &&other) noexcept(std::is_nothrow_move_assignable_v) { + calls = std::move(other.calls); + return *this; + } + + /** + * @brief Exchanges the contents with those of a given signal handler. + * @param other Signal handler to exchange the content with. + */ + void swap(sigh &other) noexcept(std::is_nothrow_swappable_v) { + using std::swap; + swap(calls, other.calls); + } + + /** + * @brief Returns the associated allocator. + * @return The associated allocator. + */ + [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { + return calls.get_allocator(); + } /** * @brief Number of listeners connected to the signal. * @return Number of listeners currently connected. */ - [[nodiscard]] size_type size() const ENTT_NOEXCEPT { + [[nodiscard]] size_type size() const noexcept { return calls.size(); } @@ -85,7 +156,7 @@ public: * @brief Returns false if at least a listener is connected to the signal. * @return True if the signal has no listeners connected, false otherwise. */ - [[nodiscard]] bool empty() const ENTT_NOEXCEPT { + [[nodiscard]] bool empty() const noexcept { return calls.empty(); } @@ -122,14 +193,18 @@ public: if constexpr(std::is_void_v) { if constexpr(std::is_invocable_r_v) { call(args...); - if(func()) { break; } + if(func()) { + break; + } } else { call(args...); func(); } } else { if constexpr(std::is_invocable_r_v) { - if(func(call(args...))) { break; } + if(func(call(args...))) { + break; + } } else { func(call(args...)); } @@ -138,10 +213,9 @@ public: } private: - std::vector> calls; + container_type calls; }; - /** * @brief Connection class. * @@ -155,18 +229,19 @@ class connection { friend class sink; connection(delegate fn, void *ref) - : disconnect{fn}, signal{ref} - {} + : disconnect{fn}, signal{ref} {} public: /*! @brief Default constructor. */ - connection() = default; + connection() + : disconnect{}, + signal{} {} /** * @brief Checks whether a connection is properly initialized. * @return True if the connection is properly initialized, false otherwise. */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { + [[nodiscard]] explicit operator bool() const noexcept { return static_cast(disconnect); } @@ -180,10 +255,9 @@ public: private: delegate disconnect; - void *signal{}; + void *signal; }; - /** * @brief Scoped connection class. * @@ -202,12 +276,18 @@ struct scoped_connection { * @param other A valid connection object. */ scoped_connection(const connection &other) - : conn{other} - {} + : conn{other} {} /*! @brief Default copy constructor, deleted on purpose. */ scoped_connection(const scoped_connection &) = delete; + /** + * @brief Move constructor. + * @param other The scoped connection to move from. + */ + scoped_connection(scoped_connection &&other) noexcept + : conn{std::exchange(other.conn, {})} {} + /*! @brief Automatically breaks the link on destruction. */ ~scoped_connection() { conn.release(); @@ -217,14 +297,24 @@ struct scoped_connection { * @brief Default copy assignment operator, deleted on purpose. * @return This scoped connection. */ - scoped_connection & operator=(const scoped_connection &) = delete; + scoped_connection &operator=(const scoped_connection &) = delete; + + /** + * @brief Move assignment operator. + * @param other The scoped connection to move from. + * @return This scoped connection. + */ + scoped_connection &operator=(scoped_connection &&other) noexcept { + conn = std::exchange(other.conn, {}); + return *this; + } /** * @brief Acquires a connection. * @param other The connection object to acquire. * @return This scoped connection. */ - scoped_connection & operator=(connection other) { + scoped_connection &operator=(connection other) { conn = std::move(other); return *this; } @@ -233,7 +323,7 @@ struct scoped_connection { * @brief Checks whether a scoped connection is properly initialized. * @return True if the connection is properly initialized, false otherwise. */ - [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT { + [[nodiscard]] explicit operator bool() const noexcept { return static_cast(conn); } @@ -246,7 +336,6 @@ private: connection conn; }; - /** * @brief Sink class. * @@ -264,11 +353,12 @@ private: * * @tparam Ret Return type of a function type. * @tparam Args Types of arguments of a function type. + * @tparam Allocator Type of allocator used to manage memory and elements. */ -template -class sink { - using signal_type = sigh; - using difference_type = typename std::iterator_traits::difference_type; +template +class sink> { + using signal_type = sigh; + using difference_type = typename signal_type::container_type::difference_type; template static void release(Type value_or_instance, void *signal) { @@ -280,21 +370,29 @@ class sink { sink{*static_cast(signal)}.disconnect(); } + auto before(delegate call) { + const auto &calls = signal->calls; + const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call)); + + sink other{*this}; + other.offset = calls.cend() - it; + return other; + } + public: /** * @brief Constructs a sink that is allowed to modify a given signal. * @param ref A valid reference to a signal object. */ - sink(sigh &ref) ENTT_NOEXCEPT + sink(sigh &ref) noexcept : offset{}, - signal{&ref} - {} + signal{&ref} {} /** * @brief Returns false if at least a listener is connected to the sink. * @return True if the sink has no listeners connected, false otherwise. */ - [[nodiscard]] bool empty() const ENTT_NOEXCEPT { + [[nodiscard]] bool empty() const noexcept { return signal->calls.empty(); } @@ -308,13 +406,7 @@ public: [[nodiscard]] sink before() { delegate call{}; call.template connect(); - - const auto &calls = signal->calls; - const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call)); - - sink other{*this}; - other.offset = std::distance(it, calls.cend()); - return other; + return before(std::move(call)); } /** @@ -329,13 +421,7 @@ public: [[nodiscard]] sink before(Type &&value_or_instance) { delegate call{}; call.template connect(value_or_instance); - - const auto &calls = signal->calls; - const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call)); - - sink other{*this}; - other.offset = std::distance(it, calls.cend()); - return other; + return before(std::move(call)); } /** @@ -345,7 +431,7 @@ public: * @param value_or_instance A valid object that fits the purpose. * @return A properly initialized sink object. */ - template + template>, void>, sink>> [[nodiscard]] sink before(Type &value_or_instance) { return before(&value_or_instance); } @@ -353,21 +439,19 @@ public: /** * @brief Returns a sink that connects before a given instance or specific * payload. - * @tparam Type Type of class or type of payload. * @param value_or_instance A valid pointer that fits the purpose. * @return A properly initialized sink object. */ - template - [[nodiscard]] sink before(Type *value_or_instance) { + [[nodiscard]] sink before(const void *value_or_instance) { sink other{*this}; if(value_or_instance) { const auto &calls = signal->calls; const auto it = std::find_if(calls.cbegin(), calls.cend(), [value_or_instance](const auto &delegate) { - return delegate.instance() == value_or_instance; + return delegate.data() == value_or_instance; }); - other.offset = std::distance(it, calls.cend()); + other.offset = calls.cend() - it; } return other; @@ -384,81 +468,47 @@ public: } /** - * @brief Connects a free function or an unbound member to a signal. + * @brief Connects a free function (with or without payload), a bound or an + * unbound member to a signal. * - * The signal handler performs checks to avoid multiple connections for the - * same function. - * - * @tparam Candidate Function or member to connect to the signal. - * @return A properly initialized connection object. - */ - template - connection connect() { - disconnect(); - - delegate call{}; - call.template connect(); - signal->calls.insert(signal->calls.end() - offset, std::move(call)); - - delegate conn{}; - conn.template connect<&release>(); - return { std::move(conn), signal }; - } - - /** - * @brief Connects a free function with payload or a bound member to a - * signal. - * - * The signal isn't responsible for the connected object or the payload. - * Users must always guarantee that the lifetime of the instance overcomes - * the one of the signal. On the other side, the signal handler performs + * The signal isn't responsible for the connected object or the payload, if + * any. Users must guarantee that the lifetime of the instance overcomes the + * one of the signal. On the other side, the signal handler performs * checks to avoid multiple connections for the same function.
* When used to connect a free function with payload, its signature must be * such that the instance is the first argument before the ones used to * define the signal itself. * * @tparam Candidate Function or member to connect to the signal. - * @tparam Type Type of class or type of payload. - * @param value_or_instance A valid object that fits the purpose. + * @tparam Type Type of class or type of payload, if any. + * @param value_or_instance A valid object that fits the purpose, if any. * @return A properly initialized connection object. */ - template - connection connect(Type &&value_or_instance) { - disconnect(value_or_instance); + template + connection connect(Type &&...value_or_instance) { + disconnect(value_or_instance...); delegate call{}; - call.template connect(value_or_instance); + call.template connect(value_or_instance...); signal->calls.insert(signal->calls.end() - offset, std::move(call)); delegate conn{}; - conn.template connect<&release>(value_or_instance); - return { std::move(conn), signal }; + conn.template connect<&release>(value_or_instance...); + return {std::move(conn), signal}; } /** - * @brief Disconnects a free function or an unbound member from a signal. + * @brief Disconnects a free function (with or without payload), a bound or + * an unbound member from a signal. * @tparam Candidate Function or member to disconnect from the signal. + * @tparam Type Type of class or type of payload, if any. + * @param value_or_instance A valid object that fits the purpose, if any. */ - template - void disconnect() { + template + void disconnect(Type &&...value_or_instance) { auto &calls = signal->calls; delegate call{}; - call.template connect(); - calls.erase(std::remove(calls.begin(), calls.end(), std::move(call)), calls.end()); - } - - /** - * @brief Disconnects a free function with payload or a bound member from a - * signal. - * @tparam Candidate Function or member to disconnect from the signal. - * @tparam Type Type of class or type of payload. - * @param value_or_instance A valid object that fits the purpose. - */ - template - void disconnect(Type &&value_or_instance) { - auto &calls = signal->calls; - delegate call{}; - call.template connect(value_or_instance); + call.template connect(value_or_instance...); calls.erase(std::remove(calls.begin(), calls.end(), std::move(call)), calls.end()); } @@ -468,7 +518,7 @@ public: * @tparam Type Type of class or type of payload. * @param value_or_instance A valid object that fits the purpose. */ - template + template>, void>>> void disconnect(Type &value_or_instance) { disconnect(&value_or_instance); } @@ -476,16 +526,13 @@ public: /** * @brief Disconnects free functions with payload or bound members from a * signal. - * @tparam Type Type of class or type of payload. * @param value_or_instance A valid object that fits the purpose. */ - template - void disconnect(Type *value_or_instance) { + void disconnect(const void *value_or_instance) { if(value_or_instance) { auto &calls = signal->calls; - calls.erase(std::remove_if(calls.begin(), calls.end(), [value_or_instance](const auto &delegate) { - return delegate.instance() == value_or_instance; - }), calls.end()); + auto predicate = [value_or_instance](const auto &delegate) { return delegate.data() == value_or_instance; }; + calls.erase(std::remove_if(calls.begin(), calls.end(), std::move(predicate)), calls.end()); } } @@ -499,22 +546,19 @@ private: signal_type *signal; }; - /** * @brief Deduction guide. * - * It allows to deduce the function type of a sink directly from the signal it - * refers to. + * It allows to deduce the signal handler type of a sink directly from the + * signal it refers to. * * @tparam Ret Return type of a function type. * @tparam Args Types of arguments of a function type. + * @tparam Allocator Type of allocator used to manage memory and elements. */ -template -sink(sigh &) --> sink; - - -} +template +sink(sigh &) -> sink>; +} // namespace entt #endif diff --git a/LiteLoader/third-party/include/httplib/httplib.h b/LiteLoader/third-party/include/httplib/httplib.h index 98f7904..8363df0 100644 --- a/LiteLoader/third-party/include/httplib/httplib.h +++ b/LiteLoader/third-party/include/httplib/httplib.h @@ -149,8 +149,8 @@ using ssize_t = long; #endif // NOMINMAX #include -#include -#include +#include +#include #ifndef WSA_FLAG_NO_HANDLE_INHERIT #define WSA_FLAG_NO_HANDLE_INHERIT 0x80 @@ -235,10 +235,10 @@ using socket_t = int; #endif #endif //_WIN32 -#include "third-party/include/openssl/err.h" -#include "third-party/include/openssl/evp.h" -#include "third-party/include/openssl/ssl.h" -#include "third-party/include/openssl/x509v3.h" +#include +#include +#include +#include #if defined(_WIN32) && defined(OPENSSL_USE_APPLINK) #include diff --git a/LiteLoader/third-party/include/magic_enum/magic_enum.hpp b/LiteLoader/third-party/include/magic_enum/magic_enum.hpp index 4464026..9aa0e69 100644 --- a/LiteLoader/third-party/include/magic_enum/magic_enum.hpp +++ b/LiteLoader/third-party/include/magic_enum/magic_enum.hpp @@ -5,11 +5,11 @@ // | | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_| // |_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____| // __/ | https://github.com/Neargye/magic_enum -// |___/ version 0.7.3 +// |___/ version 0.8.1 // // Licensed under the MIT License . // SPDX-License-Identifier: MIT -// Copyright (c) 2019 - 2021 Daniil Goncharov . +// Copyright (c) 2019 - 2022 Daniil Goncharov . // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -33,8 +33,8 @@ #define NEARGYE_MAGIC_ENUM_HPP #define MAGIC_ENUM_VERSION_MAJOR 0 -#define MAGIC_ENUM_VERSION_MINOR 7 -#define MAGIC_ENUM_VERSION_PATCH 3 +#define MAGIC_ENUM_VERSION_MINOR 8 +#define MAGIC_ENUM_VERSION_PATCH 1 #include #include @@ -44,6 +44,7 @@ #include #include #include +#include #if defined(MAGIC_ENUM_CONFIG_FILE) #include MAGIC_ENUM_CONFIG_FILE @@ -60,39 +61,42 @@ #endif #if defined(__clang__) -# pragma clang diagnostic push +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunknown-warning-option" +#pragma clang diagnostic ignored "-Wenum-constexpr-conversion" #elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" // May be used uninitialized 'return {};'. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" // May be used uninitialized 'return {};'. #elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable : 26495) // Variable 'static_string::chars_' is uninitialized. -# pragma warning(disable : 28020) // Arithmetic overflow: Using operator '-' on a 4 byte value and then casting the result to a 8 byte value. -# pragma warning(disable : 26451) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call. +#pragma warning(push) +#pragma warning(disable : 26495) // Variable 'static_string::chars_' is uninitialized. +#pragma warning(disable : 28020) // Arithmetic overflow: Using operator '-' on a 4 byte value and then casting the result to a 8 byte value. +#pragma warning(disable : 26451) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call. +#pragma warning(disable : 4514) // Unreferenced inline function has been removed. #endif // Checks magic_enum compiler compatibility. #if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 9 || defined(_MSC_VER) && _MSC_VER >= 1910 -# undef MAGIC_ENUM_SUPPORTED -# define MAGIC_ENUM_SUPPORTED 1 +#undef MAGIC_ENUM_SUPPORTED +#define MAGIC_ENUM_SUPPORTED 1 #endif // Checks magic_enum compiler aliases compatibility. #if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 9 || defined(_MSC_VER) && _MSC_VER >= 1920 -# undef MAGIC_ENUM_SUPPORTED_ALIASES -# define MAGIC_ENUM_SUPPORTED_ALIASES 1 +#undef MAGIC_ENUM_SUPPORTED_ALIASES +#define MAGIC_ENUM_SUPPORTED_ALIASES 1 #endif // Enum value must be greater or equals than MAGIC_ENUM_RANGE_MIN. By default MAGIC_ENUM_RANGE_MIN = -128. // If need another min range for all enum types by default, redefine the macro MAGIC_ENUM_RANGE_MIN. #if !defined(MAGIC_ENUM_RANGE_MIN) -# define MAGIC_ENUM_RANGE_MIN -128 +#define MAGIC_ENUM_RANGE_MIN -128 #endif // Enum value must be less or equals than MAGIC_ENUM_RANGE_MAX. By default MAGIC_ENUM_RANGE_MAX = 128. // If need another max range for all enum types by default, redefine the macro MAGIC_ENUM_RANGE_MAX. #if !defined(MAGIC_ENUM_RANGE_MAX) -# define MAGIC_ENUM_RANGE_MAX 128 +#define MAGIC_ENUM_RANGE_MAX 128 #endif namespace magic_enum { @@ -125,33 +129,59 @@ namespace customize { // If need another range for specific enum type, add specialization enum_range for necessary enum type. template struct enum_range { - static_assert(std::is_enum_v, "magic_enum::customize::enum_range requires enum type."); - static constexpr int min = MAGIC_ENUM_RANGE_MIN; - static constexpr int max = MAGIC_ENUM_RANGE_MAX; - static_assert(max > min, "magic_enum::customize::enum_range requires max > min."); + static_assert(std::is_enum_v, "magic_enum::customize::enum_range requires enum type."); + static constexpr int min = MAGIC_ENUM_RANGE_MIN; + static constexpr int max = MAGIC_ENUM_RANGE_MAX; + static_assert(max > min, "magic_enum::customize::enum_range requires max > min."); }; static_assert(MAGIC_ENUM_RANGE_MAX > MAGIC_ENUM_RANGE_MIN, "MAGIC_ENUM_RANGE_MAX must be greater than MAGIC_ENUM_RANGE_MIN."); static_assert((MAGIC_ENUM_RANGE_MAX - MAGIC_ENUM_RANGE_MIN) < (std::numeric_limits::max)(), "MAGIC_ENUM_RANGE must be less than UINT16_MAX."); +namespace detail { +enum class default_customize_tag { +}; +enum class invalid_customize_tag { +}; +} // namespace detail + +using customize_t = std::variant; + +// Default customize. +inline constexpr auto default_tag = detail::default_customize_tag{}; +// Invalid customize. +inline constexpr auto invalid_tag = detail::invalid_customize_tag{}; + // If need custom names for enum, add specialization enum_name for necessary enum type. template -constexpr string_view enum_name(E) noexcept { - static_assert(std::is_enum_v, "magic_enum::customize::enum_name requires enum type."); - - return {}; +constexpr customize_t enum_name(E) noexcept { + return default_tag; } -} // namespace magic_enum::customize +// If need custom type name for enum, add specialization enum_type_name for necessary enum type. +template +constexpr customize_t enum_type_name() noexcept { + return default_tag; +} + +} // namespace customize namespace detail { +template , std::enable_if_t, int> = 0> +using enum_constant = std::integral_constant; + +template +inline constexpr bool always_false_v = false; + template struct supported #if defined(MAGIC_ENUM_SUPPORTED) && MAGIC_ENUM_SUPPORTED || defined(MAGIC_ENUM_NO_CHECK_SUPPORT) - : std::true_type {}; +: std::true_type { +}; #else - : std::false_type {}; +: std::false_type { +}; #endif template @@ -172,262 +202,352 @@ struct range_max : std::integral_constant {}; template struct range_max::max)>> : std::integral_constant::max), customize::enum_range::max> {}; -struct char_equal_to { - constexpr bool operator()(char lhs, char rhs) const noexcept { - return lhs == rhs; - } -}; - -template +template class static_string { - public: - constexpr explicit static_string(string_view str) noexcept : static_string{str, std::make_index_sequence{}} { - assert(str.size() == N); - } +public: + constexpr explicit static_string(string_view str) noexcept + : static_string{str, std::make_integer_sequence{}} { + assert(str.size() == N); + } - constexpr const char* data() const noexcept { return chars_; } + constexpr const char* data() const noexcept { + return chars_; + } - constexpr std::size_t size() const noexcept { return N; } + constexpr std::uint16_t size() const noexcept { + return N; + } - constexpr operator string_view() const noexcept { return {data(), size()}; } + constexpr operator string_view() const noexcept { + return {data(), size()}; + } - private: - template - constexpr static_string(string_view str, std::index_sequence) noexcept : chars_{str[I]..., '\0'} {} +private: + template + constexpr static_string(string_view str, std::integer_sequence) noexcept + : chars_{str[I]..., '\0'} { + } - char chars_[N + 1]; + char chars_[static_cast(N) + 1]; }; template <> class static_string<0> { - public: - constexpr explicit static_string(string_view) noexcept {} +public: + constexpr explicit static_string() = default; - constexpr const char* data() const noexcept { return nullptr; } + constexpr explicit static_string(string_view) noexcept { + } - constexpr std::size_t size() const noexcept { return 0; } + constexpr const char* data() const noexcept { + return nullptr; + } - constexpr operator string_view() const noexcept { return {}; } + constexpr std::uint16_t size() const noexcept { + return 0; + } + + constexpr operator string_view() const noexcept { + return {}; + } }; constexpr string_view pretty_name(string_view name) noexcept { - for (std::size_t i = name.size(); i > 0; --i) { - if (!((name[i - 1] >= '0' && name[i - 1] <= '9') || - (name[i - 1] >= 'a' && name[i - 1] <= 'z') || - (name[i - 1] >= 'A' && name[i - 1] <= 'Z') || + for (std::size_t i = name.size(); i > 0; --i) { + if (!((name[i - 1] >= '0' && name[i - 1] <= '9') || + (name[i - 1] >= 'a' && name[i - 1] <= 'z') || + (name[i - 1] >= 'A' && name[i - 1] <= 'Z') || #if defined(MAGIC_ENUM_ENABLE_NONASCII) - (name[i - 1] & 0x80) || + (name[i - 1] & 0x80) || #endif - (name[i - 1] == '_'))) { - name.remove_prefix(i); - break; + (name[i - 1] == '_'))) { + name.remove_prefix(i); + break; + } } - } - if (name.size() > 0 && ((name.front() >= 'a' && name.front() <= 'z') || - (name.front() >= 'A' && name.front() <= 'Z') || + if (name.size() > 0 && ((name[0] >= 'a' && name[0] <= 'z') || + (name[0] >= 'A' && name[0] <= 'Z') || #if defined(MAGIC_ENUM_ENABLE_NONASCII) - (name.front() & 0x80) || + (name[0]) & 0x80) || #endif - (name.front() == '_'))) { - return name; - } + (name[0] == '_'))) { + return name; + } - return {}; // Invalid name. + return {}; // Invalid name. } +class case_insensitive { + static constexpr char to_lower(char c) noexcept { + return (c >= 'A' && c <= 'Z') ? static_cast(c + ('a' - 'A')) : c; + } + +public: + template + constexpr auto operator()([[maybe_unused]] L lhs, [[maybe_unused]] R rhs) const noexcept -> std::enable_if_t, char> && std::is_same_v, char>, bool> { +#if defined(MAGIC_ENUM_ENABLE_NONASCII) + static_assert(always_false_v, "magic_enum::case_insensitive not supported Non-ASCII feature."); + return false; +#else + return to_lower(lhs) == to_lower(rhs); +#endif + } +}; + constexpr std::size_t find(string_view str, char c) noexcept { #if defined(__clang__) && __clang_major__ < 9 && defined(__GLIBCXX__) || defined(_MSC_VER) && _MSC_VER < 1920 && !defined(__clang__) -// https://stackoverflow.com/questions/56484834/constexpr-stdstring-viewfind-last-of-doesnt-work-on-clang-8-with-libstdc -// https://developercommunity.visualstudio.com/content/problem/360432/vs20178-regression-c-failed-in-test.html - constexpr bool workaround = true; + // https://stackoverflow.com/questions/56484834/constexpr-stdstring-viewfind-last-of-doesnt-work-on-clang-8-with-libstdc + // https://developercommunity.visualstudio.com/content/problem/360432/vs20178-regression-c-failed-in-test.html + constexpr bool workaround = true; #else - constexpr bool workaround = false; + constexpr bool workaround = false; #endif - if constexpr (workaround) { - for (std::size_t i = 0; i < str.size(); ++i) { - if (str[i] == c) { - return i; - } - } + if constexpr (workaround) { + for (std::size_t i = 0; i < str.size(); ++i) { + if (str[i] == c) { + return i; + } + } - return string_view::npos; - } else { - return str.find_first_of(c); - } + return string_view::npos; + } else { + return str.find(c); + } } template -constexpr std::array, N> to_array(T (&a)[N], std::index_sequence) { - return {{a[I]...}}; +constexpr std::array, N> to_array(T (&a)[N], std::index_sequence) noexcept { + return {{a[I]...}}; } template -constexpr bool cmp_equal(string_view lhs, string_view rhs, BinaryPredicate&& p) noexcept(std::is_nothrow_invocable_r_v) { +constexpr bool is_default_predicate() noexcept { + return std::is_same_v, std::equal_to> || + std::is_same_v, std::equal_to<>>; +} + +template +constexpr bool is_nothrow_invocable() { + return is_default_predicate() || + std::is_nothrow_invocable_r_v; +} + +template +constexpr bool cmp_equal(string_view lhs, string_view rhs, [[maybe_unused]] BinaryPredicate&& p) noexcept(is_nothrow_invocable()) { #if defined(_MSC_VER) && _MSC_VER < 1920 && !defined(__clang__) - // https://developercommunity.visualstudio.com/content/problem/360432/vs20178-regression-c-failed-in-test.html - // https://developercommunity.visualstudio.com/content/problem/232218/c-constexpr-string-view.html - constexpr bool workaround = true; + // https://developercommunity.visualstudio.com/content/problem/360432/vs20178-regression-c-failed-in-test.html + // https://developercommunity.visualstudio.com/content/problem/232218/c-constexpr-string-view.html + constexpr bool workaround = true; #else - constexpr bool workaround = false; + constexpr bool workaround = false; #endif - constexpr bool custom_predicate = std::negation_v, char_equal_to>>; - if constexpr (custom_predicate || workaround) { - if (lhs.size() != rhs.size()) { - return false; + if constexpr (!is_default_predicate() || workaround) { + if (lhs.size() != rhs.size()) { + return false; + } + + const auto size = lhs.size(); + for (std::size_t i = 0; i < size; ++i) { + if (!p(lhs[i], rhs[i])) { + return false; + } + } + + return true; + } else { + return lhs == rhs; } - - const auto size = lhs.size(); - for (std::size_t i = 0; i < size; ++i) { - if (!p(lhs[i], rhs[i])) { - return false; - } - } - - return true; - } else { - static_cast(p); - - return lhs == rhs; - } } template constexpr bool cmp_less(L lhs, R rhs) noexcept { - static_assert(std::is_integral_v && std::is_integral_v, "magic_enum::detail::cmp_less requires integral type."); + static_assert(std::is_integral_v && std::is_integral_v, "magic_enum::detail::cmp_less requires integral type."); - if constexpr (std::is_signed_v == std::is_signed_v) { - // If same signedness (both signed or both unsigned). - return lhs < rhs; - } else if constexpr (std::is_same_v) { // bool special case - return static_cast(lhs) < rhs; - } else if constexpr (std::is_same_v) { // bool special case - return lhs < static_cast(rhs); - } else if constexpr (std::is_signed_v) { - // If 'right' is negative, then result is 'false', otherwise cast & compare. - return rhs > 0 && lhs < static_cast>(rhs); - } else { - // If 'left' is negative, then result is 'true', otherwise cast & compare. - return lhs < 0 || static_cast>(lhs) < rhs; - } + if constexpr (std::is_signed_v == std::is_signed_v) { + // If same signedness (both signed or both unsigned). + return lhs < rhs; + } else if constexpr (std::is_same_v) { // bool special case + return static_cast(lhs) < rhs; + } else if constexpr (std::is_same_v) { // bool special case + return lhs < static_cast(rhs); + } else if constexpr (std::is_signed_v) { + // If 'right' is negative, then result is 'false', otherwise cast & compare. + return rhs > 0 && lhs < static_cast>(rhs); + } else { + // If 'left' is negative, then result is 'true', otherwise cast & compare. + return lhs < 0 || static_cast>(lhs) < rhs; + } } template constexpr I log2(I value) noexcept { - static_assert(std::is_integral_v, "magic_enum::detail::log2 requires integral type."); + static_assert(std::is_integral_v, "magic_enum::detail::log2 requires integral type."); - auto ret = I{0}; - for (; value > I{1}; value >>= I{1}, ++ret) {} + if constexpr (std::is_same_v) { // bool special case + return assert(false), value; + } else { + auto ret = I{0}; + for (; value > I{1}; value >>= I{1}, ++ret) {} - return ret; + return ret; + } } template -inline constexpr bool is_enum_v = std::is_enum_v && std::is_same_v>; +inline constexpr bool is_enum_v = std::is_enum_v&& std::is_same_v>; template constexpr auto n() noexcept { - static_assert(is_enum_v, "magic_enum::detail::n requires enum type."); -#if defined(MAGIC_ENUM_SUPPORTED) && MAGIC_ENUM_SUPPORTED -# if defined(__clang__) - constexpr string_view name{__PRETTY_FUNCTION__ + 34, sizeof(__PRETTY_FUNCTION__) - 36}; -# elif defined(__GNUC__) - constexpr string_view name{__PRETTY_FUNCTION__ + 49, sizeof(__PRETTY_FUNCTION__) - 51}; -# elif defined(_MSC_VER) - constexpr string_view name{__FUNCSIG__ + 40, sizeof(__FUNCSIG__) - 57}; -# endif - return static_string{name}; + static_assert(is_enum_v, "magic_enum::detail::n requires enum type."); + + if constexpr (supported::value) { +#if defined(__clang__) || defined(__GNUC__) + constexpr auto name = pretty_name({__PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 2}); +#elif defined(_MSC_VER) + constexpr auto name = pretty_name({__FUNCSIG__, sizeof(__FUNCSIG__) - 17}); #else - return string_view{}; // Unsupported compiler. + constexpr auto name = string_view{}; #endif + return static_string{name}; + } else { + return static_string<0>{}; // Unsupported compiler or Invalid customize. + } } template -inline constexpr auto type_name_v = n(); +constexpr auto type_name() noexcept { + static_assert(is_enum_v, "magic_enum::detail::n requires enum type."); + + [[maybe_unused]] constexpr auto custom = customize::enum_type_name(); + static_assert(std::is_same_v, customize::customize_t>, "magic_enum::customize requires customize_t type."); + if constexpr (std::is_same_v, customize::customize_t> && custom.index() == 0) { + constexpr auto name = std::get(custom); + static_assert(!name.empty(), "magic_enum::customize requires not empty string."); + return static_string{name}; + } else { + return n(); + } +} + +template +inline constexpr auto type_name_v = type_name(); template constexpr auto n() noexcept { - static_assert(is_enum_v, "magic_enum::detail::n requires enum type."); - constexpr auto custom_name = customize::enum_name(V); + static_assert(is_enum_v, "magic_enum::detail::n requires enum type."); - if constexpr (custom_name.empty()) { - static_cast(custom_name); -#if defined(MAGIC_ENUM_SUPPORTED) && MAGIC_ENUM_SUPPORTED -# if defined(__clang__) || defined(__GNUC__) - constexpr auto name = pretty_name({__PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 2}); -# elif defined(_MSC_VER) - constexpr auto name = pretty_name({__FUNCSIG__, sizeof(__FUNCSIG__) - 17}); -# endif - return static_string{name}; + if constexpr (supported::value) { +#if defined(__clang__) || defined(__GNUC__) + constexpr auto name = pretty_name({__PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 2}); +#elif defined(_MSC_VER) + constexpr auto name = pretty_name({__FUNCSIG__, sizeof(__FUNCSIG__) - 17}); #else - return string_view{}; // Unsupported compiler. + constexpr auto name = string_view{}; #endif - } else { - return static_string{custom_name}; - } + return static_string{name}; + } else { + return static_string<0>{}; // Unsupported compiler or Invalid customize. + } } template -inline constexpr auto enum_name_v = n(); +constexpr auto enum_name() noexcept { + static_assert(is_enum_v, "magic_enum::detail::n requires enum type."); + + [[maybe_unused]] constexpr auto custom = customize::enum_name(V); + static_assert(std::is_same_v, customize::customize_t>, "magic_enum::customize requires customize_t type."); + if constexpr (std::is_same_v, customize::customize_t> && custom.index() == 0) { + constexpr auto name = std::get(custom); + static_assert(!name.empty(), "magic_enum::customize requires not empty string."); + return static_string{name}; + } else { + return n(); + } +} + +template +inline constexpr auto enum_name_v = enum_name(); template constexpr bool is_valid() noexcept { - static_assert(is_enum_v, "magic_enum::detail::is_valid requires enum type."); + static_assert(is_enum_v, "magic_enum::detail::is_valid requires enum type."); - return n(V)>().size() != 0; +#if defined(__clang__) && __clang_major__ >= 16 + // https://reviews.llvm.org/D130058, https://reviews.llvm.org/D131307 + constexpr E v = __builtin_bit_cast(E, V); + [[maybe_unused]] constexpr auto custom = customize::enum_name(v); + static_assert(std::is_same_v, customize::customize_t>, "magic_enum::customize requires customize_t type."); + if constexpr (std::is_same_v, customize::customize_t> && custom.index() == 0) { + constexpr auto name = std::get(custom); + static_assert(!name.empty(), "magic_enum::customize requires not empty string."); + return name.size() != 0; + } else { + return n().size() != 0; + } +#else + return enum_name(V)>().size() != 0; +#endif +} + +template > +constexpr U ualue(std::size_t i) noexcept { + static_assert(is_enum_v, "magic_enum::detail::ualue requires enum type."); + + if constexpr (std::is_same_v) { // bool special case + static_assert(O == 0, "magic_enum::detail::ualue requires valid offset."); + + return static_cast(i); + } else if constexpr (IsFlags) { + return static_cast(U{1} << static_cast(static_cast(i) + O)); + } else { + return static_cast(static_cast(i) + O); + } } template > constexpr E value(std::size_t i) noexcept { - static_assert(is_enum_v, "magic_enum::detail::value requires enum type."); + static_assert(is_enum_v, "magic_enum::detail::value requires enum type."); - if constexpr (std::is_same_v) { // bool special case - static_assert(O == 0, "magic_enum::detail::value requires valid offset."); - - return static_cast(i); - } else if constexpr (IsFlags) { - return static_cast(U{1} << static_cast(static_cast(i) + O)); - } else { - return static_cast(static_cast(i) + O); - } + return static_cast(ualue(i)); } template > constexpr int reflected_min() noexcept { - static_assert(is_enum_v, "magic_enum::detail::reflected_min requires enum type."); + static_assert(is_enum_v, "magic_enum::detail::reflected_min requires enum type."); - if constexpr (IsFlags) { - return 0; - } else { - constexpr auto lhs = range_min::value; - constexpr auto rhs = (std::numeric_limits::min)(); - - if constexpr (cmp_less(rhs, lhs)) { - return lhs; + if constexpr (IsFlags) { + return 0; } else { - return rhs; + constexpr auto lhs = range_min::value; + constexpr auto rhs = (std::numeric_limits::min)(); + + if constexpr (cmp_less(rhs, lhs)) { + return lhs; + } else { + return rhs; + } } - } } template > constexpr int reflected_max() noexcept { - static_assert(is_enum_v, "magic_enum::detail::reflected_max requires enum type."); + static_assert(is_enum_v, "magic_enum::detail::reflected_max requires enum type."); - if constexpr (IsFlags) { - return std::numeric_limits::digits - 1; - } else { - constexpr auto lhs = range_max::value; - constexpr auto rhs = (std::numeric_limits::max)(); - - if constexpr (cmp_less(lhs, rhs)) { - return lhs; + if constexpr (IsFlags) { + return std::numeric_limits::digits - 1; } else { - return rhs; + constexpr auto lhs = range_max::value; + constexpr auto rhs = (std::numeric_limits::max)(); + + if constexpr (cmp_less(lhs, rhs)) { + return lhs; + } else { + return rhs; + } } - } } template @@ -438,81 +558,81 @@ inline constexpr auto reflected_max_v = reflected_max(); template constexpr std::size_t values_count(const bool (&valid)[N]) noexcept { - auto count = std::size_t{0}; - for (std::size_t i = 0; i < N; ++i) { - if (valid[i]) { - ++count; + auto count = std::size_t{0}; + for (std::size_t i = 0; i < N; ++i) { + if (valid[i]) { + ++count; + } } - } - return count; + return count; } template constexpr auto values(std::index_sequence) noexcept { - static_assert(is_enum_v, "magic_enum::detail::values requires enum type."); - constexpr bool valid[sizeof...(I)] = {is_valid(I)>()...}; - constexpr std::size_t count = values_count(valid); + static_assert(is_enum_v, "magic_enum::detail::values requires enum type."); + constexpr bool valid[sizeof...(I)] = {is_valid(I)>()...}; + constexpr std::size_t count = values_count(valid); - if constexpr (count > 0) { - E values[count] = {}; - for (std::size_t i = 0, v = 0; v < count; ++i) { - if (valid[i]) { - values[v++] = value(i); - } + if constexpr (count > 0) { + E values[count] = {}; + for (std::size_t i = 0, v = 0; v < count; ++i) { + if (valid[i]) { + values[v++] = value(i); + } + } + + return to_array(values, std::make_index_sequence{}); + } else { + return std::array{}; } - - return to_array(values, std::make_index_sequence{}); - } else { - return std::array{}; - } } template > constexpr auto values() noexcept { - static_assert(is_enum_v, "magic_enum::detail::values requires enum type."); - constexpr auto min = reflected_min_v; - constexpr auto max = reflected_max_v; - constexpr auto range_size = max - min + 1; - static_assert(range_size > 0, "magic_enum::enum_range requires valid size."); - static_assert(range_size < (std::numeric_limits::max)(), "magic_enum::enum_range requires valid size."); + static_assert(is_enum_v, "magic_enum::detail::values requires enum type."); + constexpr auto min = reflected_min_v; + constexpr auto max = reflected_max_v; + constexpr auto range_size = max - min + 1; + static_assert(range_size > 0, "magic_enum::enum_range requires valid size."); + static_assert(range_size < (std::numeric_limits::max)(), "magic_enum::enum_range requires valid size."); - return values>(std::make_index_sequence{}); + return values(std::make_index_sequence{}); } template > constexpr bool is_flags_enum() noexcept { - static_assert(is_enum_v, "magic_enum::detail::is_flags_enum requires enum type."); + static_assert(is_enum_v, "magic_enum::detail::is_flags_enum requires enum type."); - if constexpr (has_is_flags::value) { - return customize::enum_range::is_flags; - } else if constexpr (std::is_same_v) { // bool special case - return false; - } else { -#if defined(MAGIC_ENUM_NO_CHECK_FLAGS) - return false; -#else - constexpr auto flags_values = values(); - constexpr auto default_values = values(); - if (flags_values.size() == 0 || default_values.size() > flags_values.size()) { - return false; - } - for (std::size_t i = 0; i < default_values.size(); ++i) { - const auto v = static_cast(default_values[i]); - if (v != 0 && (v & (v - 1)) != 0) { + if constexpr (has_is_flags::value) { + return customize::enum_range::is_flags; + } else if constexpr (std::is_same_v) { // bool special case return false; - } - } - return flags_values.size() > 0; + } else { +#if defined(MAGIC_ENUM_NO_CHECK_FLAGS) + return false; +#else + constexpr auto flags_values = values(); + constexpr auto default_values = values(); + if (flags_values.size() == 0 || default_values.size() > flags_values.size()) { + return false; + } + for (std::size_t i = 0; i < default_values.size(); ++i) { + const auto v = static_cast(default_values[i]); + if (v != 0 && (v & (v - 1)) != 0) { + return false; + } + } + return flags_values.size() > 0; #endif - } + } } template inline constexpr bool is_flags_v = is_flags_enum(); template -inline constexpr auto values_v = values>(); +inline constexpr std::array values_v = values>(); template > using values_t = decltype((values_v)); @@ -528,38 +648,45 @@ inline constexpr auto max_v = (count_v > 0) ? static_cast(values_v.back template constexpr auto names(std::index_sequence) noexcept { - static_assert(is_enum_v, "magic_enum::detail::names requires enum type."); + static_assert(is_enum_v, "magic_enum::detail::names requires enum type."); - return std::array{{enum_name_v[I]>...}}; + return std::array{{enum_name_v[I]>...}}; } template -inline constexpr auto names_v = names(std::make_index_sequence>{}); +inline constexpr std::array names_v = names(std::make_index_sequence>{}); template > using names_t = decltype((names_v)); template constexpr auto entries(std::index_sequence) noexcept { - static_assert(is_enum_v, "magic_enum::detail::entries requires enum type."); + static_assert(is_enum_v, "magic_enum::detail::entries requires enum type."); - return std::array, sizeof...(I)>{{{values_v[I], enum_name_v[I]>}...}}; + return std::array, sizeof...(I)>{{{values_v[I], enum_name_v[I]>}...}}; } template -inline constexpr auto entries_v = entries(std::make_index_sequence>{}); +inline constexpr std::array entries_v = entries(std::make_index_sequence>{}); template > using entries_t = decltype((entries_v)); template > constexpr bool is_sparse() noexcept { - static_assert(is_enum_v, "magic_enum::detail::is_sparse requires enum type."); - constexpr auto max = is_flags_v ? log2(max_v) : max_v; - constexpr auto min = is_flags_v ? log2(min_v) : min_v; - constexpr auto range_size = max - min + 1; + static_assert(is_enum_v, "magic_enum::detail::is_sparse requires enum type."); - return range_size != count_v; + if constexpr (count_v == 0) { + return false; + } else if constexpr (std::is_same_v) { // bool special case + return false; + } else { + constexpr auto max = is_flags_v ? log2(max_v) : max_v; + constexpr auto min = is_flags_v ? log2(min_v) : min_v; + constexpr auto range_size = max - min + 1; + + return range_size != count_v; + } } template @@ -567,30 +694,29 @@ inline constexpr bool is_sparse_v = is_sparse(); template > constexpr U values_ors() noexcept { - static_assert(is_enum_v, "magic_enum::detail::values_ors requires enum type."); + static_assert(is_enum_v, "magic_enum::detail::values_ors requires enum type."); - auto ors = U{0}; - for (std::size_t i = 0; i < count_v; ++i) { - ors |= static_cast(values_v[i]); - } + auto ors = U{0}; + for (std::size_t i = 0; i < count_v; ++i) { + ors |= static_cast(values_v[i]); + } - return ors; + return ors; } -template +template struct enable_if_enum {}; -template -struct enable_if_enum { - using type = R; - using D = std::decay_t; - static_assert(supported::value, "magic_enum unsupported compiler (https://github.com/Neargye/magic_enum#compiler-compatibility)."); +template +struct enable_if_enum { + using type = R; + static_assert(supported::value, "magic_enum unsupported compiler (https://github.com/Neargye/magic_enum#compiler-compatibility)."); }; -template -using enable_if_enum_t = std::enable_if_t>, R>; +template > +using enable_if_t = typename enable_if_enum> && std::is_invocable_r_v, R>::type; -template >>> +template >, int> = 0> using enum_concept = T; template > @@ -611,7 +737,252 @@ struct underlying_type {}; template struct underlying_type : std::underlying_type> {}; -} // namespace magic_enum::detail +#if defined(MAGIC_ENUM_NO_HASH) +template +inline constexpr bool has_hash = false; +#else +template +inline constexpr bool has_hash = true; + +template +struct constexpr_hash_t; + +template +struct constexpr_hash_t>> { + constexpr auto operator()(Value value) const noexcept { + using U = typename underlying_type::type; + if constexpr (std::is_same_v) { // bool special case + return static_cast(value); + } else { + return static_cast(value); + } + } + using secondary_hash = constexpr_hash_t; +}; + +template +struct constexpr_hash_t>> { + static constexpr std::uint32_t crc_table[256]{ + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, + 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, + 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, + 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, + 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, + 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, + 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, + 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, + 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, + 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, + 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, + 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, + 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, + 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, + 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, + 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, + 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, + 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, + 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, + 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, + 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, + 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, + 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, + 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, + 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, + 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL}; + constexpr std::uint32_t operator()(string_view value) const noexcept { + auto crc = static_cast(0xffffffffL); + for (const auto c : value) { + crc = (crc >> 8) ^ crc_table[(crc ^ static_cast(c)) & 0xff]; + } + return crc ^ 0xffffffffL; + } + + struct secondary_hash { + constexpr std::uint32_t operator()(string_view value) const noexcept { + auto acc = static_cast(2166136261ULL); + for (const auto c : value) { + acc = ((acc ^ static_cast(c)) * static_cast(16777619ULL)) & (std::numeric_limits::max)(); + } + return static_cast(acc); + } + }; +}; + +template +inline constexpr Hash hash_v{}; + +template +constexpr auto calculate_cases(std::size_t Page) noexcept { + constexpr std::array values = *GlobValues; + constexpr std::size_t size = values.size(); + + using switch_t = std::invoke_result_t; + static_assert(std::is_integral_v && !std::is_same_v); + const std::size_t values_to = (std::min)(static_cast(256), size - Page); + + std::array result{}; + auto fill = result.begin(); + { + auto first = values.begin() + static_cast(Page); + auto last = values.begin() + static_cast(Page + values_to); + while (first != last) { + *fill++ = hash_v(*first++); + } + } + + // dead cases, try to avoid case collisions + for (switch_t last_value = result[values_to - 1]; fill != result.end() && last_value != (std::numeric_limits::max)(); *fill++ = ++last_value) { + } + + { + auto it = result.begin(); + auto last_value = (std::numeric_limits::min)(); + for (; fill != result.end(); *fill++ = last_value++) { + while (last_value == *it) { + ++last_value, ++it; + } + } + } + + return result; +} + +template +constexpr R invoke_r(F&& f, Args&&... args) noexcept(std::is_nothrow_invocable_r_v) { + if constexpr (std::is_void_v) { + std::forward(f)(std::forward(args)...); + } else { + return static_cast(std::forward(f)(std::forward(args)...)); + } +} + +enum class case_call_t { + index, + value +}; + +template +inline constexpr auto default_result_type_lambda = []() noexcept(std::is_nothrow_default_constructible_v) { return T{}; }; + +template <> +inline constexpr auto default_result_type_lambda = []() noexcept {}; + +template +constexpr bool no_duplicate() noexcept { + using value_t = std::decay_t; + using hash_value_t = std::invoke_result_t; + std::arraysize()> hashes{}; + std::size_t size = 0; + for (auto elem : *Arr) { + hashes[size] = hash_v(elem); + for (auto i = size++; i > 0; --i) { + if (hashes[i] < hashes[i - 1]) { + auto tmp = hashes[i]; + hashes[i] = hashes[i - 1]; + hashes[i - 1] = tmp; + } else if (hashes[i] == hashes[i - 1]) { + return false; + } else { + break; + } + } + } + return true; +} + +#define MAGIC_ENUM_FOR_EACH_256(T) T(0) T(1) T(2) T(3) T(4) T(5) T(6) T(7) T(8) T(9) T(10) T(11) T(12) T(13) T(14) T(15) T(16) T(17) T(18) T(19) T(20) T(21) T(22) T(23) T(24) T(25) T(26) T(27) T(28) T(29) T(30) T(31) \ + T(32) T(33) T(34) T(35) T(36) T(37) T(38) T(39) T(40) T(41) T(42) T(43) T(44) T(45) T(46) T(47) T(48) T(49) T(50) T(51) T(52) T(53) T(54) T(55) T(56) T(57) T(58) T(59) T(60) T(61) T(62) T(63) \ + T(64) T(65) T(66) T(67) T(68) T(69) T(70) T(71) T(72) T(73) T(74) T(75) T(76) T(77) T(78) T(79) T(80) T(81) T(82) T(83) T(84) T(85) T(86) T(87) T(88) T(89) T(90) T(91) T(92) T(93) T(94) T(95) \ + T(96) T(97) T(98) T(99) T(100) T(101) T(102) T(103) T(104) T(105) T(106) T(107) T(108) T(109) T(110) T(111) T(112) T(113) T(114) T(115) T(116) T(117) T(118) T(119) T(120) T(121) T(122) T(123) T(124) T(125) T(126) T(127) \ + T(128) T(129) T(130) T(131) T(132) T(133) T(134) T(135) T(136) T(137) T(138) T(139) T(140) T(141) T(142) T(143) T(144) T(145) T(146) T(147) T(148) T(149) T(150) T(151) T(152) T(153) T(154) T(155) T(156) T(157) T(158) T(159) \ + T(160) T(161) T(162) T(163) T(164) T(165) T(166) T(167) T(168) T(169) T(170) T(171) T(172) T(173) T(174) T(175) T(176) T(177) T(178) T(179) T(180) T(181) T(182) T(183) T(184) T(185) T(186) T(187) T(188) T(189) T(190) T(191) \ + T(192) T(193) T(194) T(195) T(196) T(197) T(198) T(199) T(200) T(201) T(202) T(203) T(204) T(205) T(206) T(207) T(208) T(209) T(210) T(211) T(212) T(213) T(214) T(215) T(216) T(217) T(218) T(219) T(220) T(221) T(222) T(223) \ + T(224) T(225) T(226) T(227) T(228) T(229) T(230) T(231) T(232) T(233) T(234) T(235) T(236) T(237) T(238) T(239) T(240) T(241) T(242) T(243) T(244) T(245) T(246) T(247) T(248) T(249) T(250) T(251) T(252) T(253) T(254) T(255) + +#define MAGIC_ENUM_CASE(val) \ + case cases[val]: \ + if constexpr ((val) + Page < size) { \ + if (!pred(values[val + Page], searched)) { \ + break; \ + } \ + if constexpr (CallValue == case_call_t::index) { \ + if constexpr (std::is_invocable_r_v>) { \ + return detail::invoke_r(std::forward(lambda), std::integral_constant{}); \ + } else if constexpr (std::is_invocable_v>) { \ + assert(false && "magic_enum::detail::constexpr_switch wrong result type."); \ + } \ + } else if constexpr (CallValue == case_call_t::value) { \ + if constexpr (std::is_invocable_r_v>) { \ + return detail::invoke_r(std::forward(lambda), enum_constant{}); \ + } else if constexpr (std::is_invocable_r_v>) { \ + assert(false && "magic_enum::detail::constexpr_switch wrong result type."); \ + } \ + } \ + break; \ + } else \ + [[fallthrough]]; + +template ::value_type>, + typename Lambda, typename ResultGetterType = decltype(default_result_type_lambda<>), + typename BinaryPredicate = std::equal_to<>> +constexpr std::invoke_result_t constexpr_switch( + Lambda&& lambda, + typename std::decay_t::value_type searched, + ResultGetterType&& def = default_result_type_lambda<>, + BinaryPredicate&& pred = {}) { + using result_t = std::invoke_result_t; + using hash_t = std::conditional_t(), Hash, typename Hash::secondary_hash>; + constexpr std::array values = *GlobValues; + constexpr std::size_t size = values.size(); + constexpr std::array cases = calculate_cases(Page); + + switch (hash_v(searched)) { + MAGIC_ENUM_FOR_EACH_256(MAGIC_ENUM_CASE) + default: + if constexpr (size > 256 + Page) { + return constexpr_switch(std::forward(lambda), searched, std::forward(def)); + } + break; + } + return def(); +} + +#undef MAGIC_ENUM_FOR_EACH_256 +#undef MAGIC_ENUM_CASE +#endif + +template +constexpr auto for_each(Lambda&& lambda, std::index_sequence) { + static_assert(is_enum_v, "magic_enum::detail::for_each requires enum type."); + constexpr bool has_void_return = (std::is_void_v[I]>>> || ...); + constexpr bool all_same_return = (std::is_same_v[0]>>, std::invoke_result_t[I]>>> && ...); + + if constexpr (has_void_return) { + (lambda(enum_constant[I]> {}), ...); + } else if constexpr (all_same_return) { + return std::array{lambda(enum_constant[I]> {})...}; + } else { + return std::tuple{lambda(enum_constant[I]> {})...}; + } +} + +template +constexpr bool all_invocable(std::index_sequence) { + static_assert(is_enum_v, "magic_enum::detail::all_invocable requires enum type."); + + return (std::is_invocable_v[I]>> && ...); +} + +} // namespace detail // Checks is magic_enum supported compiler. inline constexpr bool is_magic_enum_supported = detail::supported::value; @@ -643,343 +1014,491 @@ struct underlying_type : detail::underlying_type {}; template using underlying_type_t = typename underlying_type::type; +template +using enum_constant = detail::enum_constant; + // Returns type name of enum. template -[[nodiscard]] constexpr auto enum_type_name() noexcept -> detail::enable_if_enum_t { - constexpr string_view name = detail::type_name_v>; - static_assert(name.size() > 0, "Enum type does not have a name."); +[[nodiscard]] constexpr auto enum_type_name() noexcept -> detail::enable_if_t { + constexpr string_view name = detail::type_name_v>; + static_assert(!name.empty(), "magic_enum::enum_type_name enum type does not have a name."); - return name; + return name; } // Returns number of enum values. template -[[nodiscard]] constexpr auto enum_count() noexcept -> detail::enable_if_enum_t { - return detail::count_v>; +[[nodiscard]] constexpr auto enum_count() noexcept -> detail::enable_if_t { + return detail::count_v>; } // Returns enum value at specified index. // No bounds checking is performed: the behavior is undefined if index >= number of enum values. template -[[nodiscard]] constexpr auto enum_value(std::size_t index) noexcept -> detail::enable_if_enum_t> { - using D = std::decay_t; +[[nodiscard]] constexpr auto enum_value(std::size_t index) noexcept -> detail::enable_if_t> { + using D = std::decay_t; - if constexpr (detail::is_sparse_v) { - return assert((index < detail::count_v)), detail::values_v[index]; - } else { - constexpr bool is_flag = detail::is_flags_v; - constexpr auto min = is_flag ? detail::log2(detail::min_v) : detail::min_v; + if constexpr (detail::is_sparse_v) { + return assert((index < detail::count_v)), detail::values_v[index]; + } else { + constexpr bool is_flag = detail::is_flags_v; + constexpr auto min = is_flag ? detail::log2(detail::min_v) : detail::min_v; - return assert((index < detail::count_v)), detail::value(index); - } + return assert((index < detail::count_v)), detail::value(index); + } } // Returns enum value at specified index. template -[[nodiscard]] constexpr auto enum_value() noexcept -> detail::enable_if_enum_t> { - return enum_value>(I); +[[nodiscard]] constexpr auto enum_value() noexcept -> detail::enable_if_t> { + using D = std::decay_t; + static_assert(I < detail::count_v, "magic_enum::enum_value out of range."); + + return enum_value(I); } // Returns std::array with enum values, sorted by enum value. template -[[nodiscard]] constexpr auto enum_values() noexcept -> detail::enable_if_enum_t> { - return detail::values_v>; -} - -// Returns name from static storage enum variable. -// This version is much lighter on the compile times and is not restricted to the enum_range limitation. -template -[[nodiscard]] constexpr auto enum_name() noexcept -> detail::enable_if_enum_t { - constexpr string_view name = detail::enum_name_v, V>; - static_assert(name.size() > 0, "Enum value does not have a name."); - - return name; -} - -// Returns name from enum value. -// If enum value does not have name or value out of range, returns empty string. -template -[[nodiscard]] constexpr auto enum_name(E value) noexcept -> detail::enable_if_enum_t { - using D = std::decay_t; - using U = underlying_type_t; - - if constexpr (detail::is_sparse_v || detail::is_flags_v) { - for (std::size_t i = 0; i < detail::count_v; ++i) { - if (enum_value(i) == value) { - return detail::names_v[i]; - } - } - } else { - const auto v = static_cast(value); - if (v >= detail::min_v && v <= detail::max_v) { - return detail::names_v[static_cast(v - detail::min_v)]; - } - } - - return {}; // Invalid value or out of range. -} - -// Returns name from enum-flags value. -// If enum-flags value does not have name or value out of range, returns empty string. -template -[[nodiscard]] auto enum_flags_name(E value) -> detail::enable_if_enum_t { - using D = std::decay_t; - using U = underlying_type_t; - - if constexpr (detail::is_flags_v) { - string name; - auto check_value = U{0}; - for (std::size_t i = 0; i < detail::count_v; ++i) { - if (const auto v = static_cast(enum_value(i)); (static_cast(value) & v) != 0) { - check_value |= v; - const auto n = detail::names_v[i]; - if (!name.empty()) { - name.append(1, '|'); - } - name.append(n.data(), n.size()); - } - } - - if (check_value != 0 && check_value == static_cast(value)) { - return name; - } - - return {}; // Invalid value or out of range. - } else { - return string{enum_name(value)}; - } -} - -// Returns std::array with names, sorted by enum value. -template -[[nodiscard]] constexpr auto enum_names() noexcept -> detail::enable_if_enum_t> { - return detail::names_v>; -} - -// Returns std::array with pairs (value, name), sorted by enum value. -template -[[nodiscard]] constexpr auto enum_entries() noexcept -> detail::enable_if_enum_t> { - return detail::entries_v>; -} - -// Obtains enum value from integer value. -// Returns optional with enum value. -template -[[nodiscard]] constexpr auto enum_cast(underlying_type_t value) noexcept -> detail::enable_if_enum_t>> { - using D = std::decay_t; - using U = underlying_type_t; - - if constexpr (detail::is_sparse_v) { - constexpr auto count = detail::count_v; - if constexpr (detail::is_flags_v) { - auto check_value = U{0}; - for (std::size_t i = 0; i < count; ++i) { - if (const auto v = static_cast(enum_value(i)); (value & v) != 0) { - check_value |= v; - } - } - - if (check_value != 0 && check_value == value) { - return static_cast(value); - } - } else { - for (std::size_t i = 0; i < count; ++i) { - if (value == static_cast(enum_value(i))) { - return static_cast(value); - } - } - } - } else { - constexpr auto min = detail::min_v; - constexpr auto max = detail::is_flags_v ? detail::values_ors() : detail::max_v; - - if (value >= min && value <= max) { - return static_cast(value); - } - } - - return {}; // Invalid value or out of range. -} - -// Obtains enum value from name. -// Returns optional with enum value. -template -[[nodiscard]] constexpr auto enum_cast(string_view value, BinaryPredicate p) noexcept(std::is_nothrow_invocable_r_v) -> detail::enable_if_enum_t>> { - static_assert(std::is_invocable_r_v, "magic_enum::enum_cast requires bool(char, char) invocable predicate."); - using D = std::decay_t; - using U = underlying_type_t; - - if constexpr (detail::is_flags_v) { - auto result = U{0}; - while (!value.empty()) { - const auto d = detail::find(value, '|'); - const auto s = (d == string_view::npos) ? value : value.substr(0, d); - auto f = U{0}; - for (std::size_t i = 0; i < detail::count_v; ++i) { - if (detail::cmp_equal(s, detail::names_v[i], p)) { - f = static_cast(enum_value(i)); - result |= f; - break; - } - } - if (f == U{0}) { - return {}; // Invalid value or out of range. - } - value.remove_prefix((d == string_view::npos) ? value.size() : d + 1); - } - - if (result != U{0}) { - return static_cast(result); - } - } else { - for (std::size_t i = 0; i < detail::count_v; ++i) { - if (detail::cmp_equal(value, detail::names_v[i], p)) { - return enum_value(i); - } - } - } - - return {}; // Invalid value or out of range. -} - -// Obtains enum value from name. -// Returns optional with enum value. -template -[[nodiscard]] constexpr auto enum_cast(string_view value) noexcept -> detail::enable_if_enum_t>> { - using D = std::decay_t; - - return enum_cast(value, detail::char_equal_to{}); +[[nodiscard]] constexpr auto enum_values() noexcept -> detail::enable_if_t> { + return detail::values_v>; } // Returns integer value from enum value. template -[[nodiscard]] constexpr auto enum_integer(E value) noexcept -> detail::enable_if_enum_t> { - return static_cast>(value); +[[nodiscard]] constexpr auto enum_integer(E value) noexcept -> detail::enable_if_t> { + return static_cast>(value); +} + +// Returns underlying value from enum value. +template +[[nodiscard]] constexpr auto enum_underlying(E value) noexcept -> detail::enable_if_t> { + return static_cast>(value); } // Obtains index in enum values from enum value. // Returns optional with index. template -[[nodiscard]] constexpr auto enum_index(E value) noexcept -> detail::enable_if_enum_t> { - using D = std::decay_t; - using U = underlying_type_t; +[[nodiscard]] constexpr auto enum_index(E value) noexcept -> detail::enable_if_t> { + using D = std::decay_t; + using U = underlying_type_t; - if constexpr (detail::is_sparse_v || detail::is_flags_v) { - for (std::size_t i = 0; i < detail::count_v; ++i) { - if (enum_value(i) == value) { - return i; - } + if constexpr (detail::count_v == 0) { + return {}; // Empty enum. + } else if constexpr (detail::is_sparse_v || detail::is_flags_v) { +#if defined(MAGIC_ENUM_NO_HASH) + for (std::size_t i = 0; i < detail::count_v; ++i) { + if (enum_value(i) == value) { + return i; + } + } + return {}; // Invalid value or out of range. +#else + return detail::constexpr_switch<&detail::values_v, detail::case_call_t::index>( + [](std::size_t i) { return optional{i}; }, + value, + detail::default_result_type_lambda>); +#endif + } else { + const auto v = static_cast(value); + if (v >= detail::min_v && v <= detail::max_v) { + return static_cast(v - detail::min_v); + } + return {}; // Invalid value or out of range. } - } else { - const auto v = static_cast(value); - if (v >= detail::min_v && v <= detail::max_v) { - return static_cast(v - detail::min_v); - } - } +} - return {}; // Invalid value or out of range. +// Obtains index in enum values from static storage enum variable. +template +[[nodiscard]] constexpr auto enum_index() noexcept -> detail::enable_if_t { + constexpr auto index = enum_index>(V); + static_assert(index, "magic_enum::enum_index enum value does not have a index."); + + return *index; +} + +// Returns name from static storage enum variable. +// This version is much lighter on the compile times and is not restricted to the enum_range limitation. +template +[[nodiscard]] constexpr auto enum_name() noexcept -> detail::enable_if_t { + constexpr string_view name = detail::enum_name_v, V>; + static_assert(!name.empty(), "magic_enum::enum_name enum value does not have a name."); + + return name; +} + +// Returns name from enum value. +// If enum value does not have name or value out of range, returns empty string. +template +[[nodiscard]] constexpr auto enum_name(E value) noexcept -> detail::enable_if_t { + using D = std::decay_t; + + if (const auto i = enum_index(value)) { + return detail::names_v[*i]; + } + return {}; +} + +// Returns name from enum-flags value. +// If enum-flags value does not have name or value out of range, returns empty string. +template +[[nodiscard]] auto enum_flags_name(E value) -> detail::enable_if_t { + using D = std::decay_t; + using U = underlying_type_t; + + if constexpr (detail::is_flags_v) { + string name; + auto check_value = U{0}; + for (std::size_t i = 0; i < detail::count_v; ++i) { + if (const auto v = static_cast(enum_value(i)); (static_cast(value) & v) != 0) { + check_value |= v; + const auto n = detail::names_v[i]; + if (!name.empty()) { + name.append(1, '|'); + } + name.append(n.data(), n.size()); + } + } + + if (check_value != 0 && check_value == static_cast(value)) { + return name; + } + + return {}; // Invalid value or out of range. + } else { + if (const auto name = enum_name(value); !name.empty()) { + return {name.data(), name.size()}; + } + return {}; // Invalid value or out of range. + } +} + +// Returns std::array with names, sorted by enum value. +template +[[nodiscard]] constexpr auto enum_names() noexcept -> detail::enable_if_t> { + return detail::names_v>; +} + +// Returns std::array with pairs (value, name), sorted by enum value. +template +[[nodiscard]] constexpr auto enum_entries() noexcept -> detail::enable_if_t> { + return detail::entries_v>; +} + +// Allows you to write magic_enum::enum_cast("bar", magic_enum::case_insensitive); +inline constexpr auto case_insensitive = detail::case_insensitive{}; + +// Obtains enum value from integer value. +// Returns optional with enum value. +template +[[nodiscard]] constexpr auto enum_cast(underlying_type_t value) noexcept -> detail::enable_if_t>> { + using D = std::decay_t; + using U = underlying_type_t; + + if constexpr (detail::count_v == 0) { + return {}; // Empty enum. + } else if constexpr (detail::is_sparse_v) { + if constexpr (detail::is_flags_v) { + auto check_value = U{0}; + for (std::size_t i = 0; i < detail::count_v; ++i) { + if (const auto v = static_cast(enum_value(i)); (value & v) != 0) { + check_value |= v; + } + } + + if (check_value != 0 && check_value == value) { + return static_cast(value); + } + return {}; // Invalid value or out of range. + } else { +#if defined(MAGIC_ENUM_NO_HASH) + for (std::size_t i = 0; i < detail::count_v; ++i) { + if (value == static_cast(enum_value(i))) { + return static_cast(value); + } + } + return {}; // Invalid value or out of range. +#else + return detail::constexpr_switch<&detail::values_v, detail::case_call_t::value>( + [](D v) { return optional{v}; }, + static_cast(value), + detail::default_result_type_lambda>); +#endif + } + } else { + constexpr auto min = detail::min_v; + constexpr auto max = detail::is_flags_v ? detail::values_ors() : detail::max_v; + + if (value >= min && value <= max) { + return static_cast(value); + } + return {}; // Invalid value or out of range. + } +} + +// Obtains enum value from name. +// Returns optional with enum value. +template > +[[nodiscard]] constexpr auto enum_cast(string_view value, [[maybe_unused]] BinaryPredicate&& p = {}) noexcept(detail::is_nothrow_invocable()) -> detail::enable_if_t>, BinaryPredicate> { + static_assert(std::is_invocable_r_v, "magic_enum::enum_cast requires bool(char, char) invocable predicate."); + using D = std::decay_t; + using U = underlying_type_t; + + if constexpr (detail::count_v == 0) { + return {}; // Empty enum. + } else if constexpr (detail::is_flags_v) { + auto result = U{0}; + while (!value.empty()) { + const auto d = detail::find(value, '|'); + const auto s = (d == string_view::npos) ? value : value.substr(0, d); + auto f = U{0}; + for (std::size_t i = 0; i < detail::count_v; ++i) { + if (detail::cmp_equal(s, detail::names_v[i], p)) { + f = static_cast(enum_value(i)); + result |= f; + break; + } + } + if (f == U{0}) { + return {}; // Invalid value or out of range. + } + value.remove_prefix((d == string_view::npos) ? value.size() : d + 1); + } + + if (result != U{0}) { + return static_cast(result); + } + return {}; // Invalid value or out of range. + } else if constexpr (detail::count_v > 0) { + if constexpr (detail::is_default_predicate()) { +#if defined(MAGIC_ENUM_NO_HASH) + for (std::size_t i = 0; i < detail::count_v; ++i) { + if (detail::cmp_equal(value, detail::names_v[i], p)) { + return enum_value(i); + } + } + return {}; // Invalid value or out of range. +#else + return detail::constexpr_switch<&detail::names_v, detail::case_call_t::index>( + [](std::size_t i) { return optional{detail::values_v[i]}; }, + value, + detail::default_result_type_lambda>, + [&p](string_view lhs, string_view rhs) { return detail::cmp_equal(lhs, rhs, p); }); +#endif + } else { + for (std::size_t i = 0; i < detail::count_v; ++i) { + if (detail::cmp_equal(value, detail::names_v[i], p)) { + return enum_value(i); + } + } + return {}; // Invalid value or out of range. + } + } } // Checks whether enum contains enumerator with such enum value. template -[[nodiscard]] constexpr auto enum_contains(E value) noexcept -> detail::enable_if_enum_t { - using D = std::decay_t; - using U = underlying_type_t; +[[nodiscard]] constexpr auto enum_contains(E value) noexcept -> detail::enable_if_t { + using D = std::decay_t; + using U = underlying_type_t; - return enum_cast(static_cast(value)).has_value(); + return static_cast(enum_cast(static_cast(value))); } // Checks whether enum contains enumerator with such integer value. template -[[nodiscard]] constexpr auto enum_contains(underlying_type_t value) noexcept -> detail::enable_if_enum_t { - return enum_cast>(value).has_value(); +[[nodiscard]] constexpr auto enum_contains(underlying_type_t value) noexcept -> detail::enable_if_t { + using D = std::decay_t; + + return static_cast(enum_cast(value)); } // Checks whether enum contains enumerator with such name. -template -[[nodiscard]] constexpr auto enum_contains(string_view value, BinaryPredicate p) noexcept(std::is_nothrow_invocable_r_v) -> detail::enable_if_enum_t { - static_assert(std::is_invocable_r_v, "magic_enum::enum_contains requires bool(char, char) invocable predicate."); +template > +[[nodiscard]] constexpr auto enum_contains(string_view value, BinaryPredicate&& p = {}) noexcept(detail::is_nothrow_invocable()) -> detail::enable_if_t { + static_assert(std::is_invocable_r_v, "magic_enum::enum_contains requires bool(char, char) invocable predicate."); + using D = std::decay_t; - return enum_cast>(value, std::move_if_noexcept(p)).has_value(); + return static_cast(enum_cast(value, std::forward(p))); } -// Checks whether enum contains enumerator with such name. -template -[[nodiscard]] constexpr auto enum_contains(string_view value) noexcept -> detail::enable_if_enum_t { - return enum_cast>(value).has_value(); +template +constexpr auto enum_switch(Lambda&& lambda, E value) -> detail::enable_if_t { + using D = std::decay_t; + static_assert(detail::has_hash, "magic_enum::enum_switch requires no defined MAGIC_ENUM_NO_HASH"); + + return detail::constexpr_switch<&detail::values_v, detail::case_call_t::value>( + std::forward(lambda), + value, + detail::default_result_type_lambda); +} + +template +constexpr auto enum_switch(Lambda&& lambda, E value, Result&& result) -> detail::enable_if_t { + using D = std::decay_t; + static_assert(detail::has_hash, "magic_enum::enum_switch requires no defined MAGIC_ENUM_NO_HASH"); + + return detail::constexpr_switch<&detail::values_v, detail::case_call_t::value>( + std::forward(lambda), + value, + [&result] { return std::forward(result); }); +} + +template , typename Lambda> +constexpr auto enum_switch(Lambda&& lambda, string_view name, BinaryPredicate&& p = {}) -> detail::enable_if_t { + static_assert(std::is_invocable_r_v, "magic_enum::enum_switch requires bool(char, char) invocable predicate."); + using D = std::decay_t; + static_assert(detail::has_hash, "magic_enum::enum_switch requires no defined MAGIC_ENUM_NO_HASH"); + + if (const auto v = enum_cast(name, std::forward(p))) { + return enum_switch(std::forward(lambda), *v); + } + return detail::default_result_type_lambda(); +} + +template , typename Lambda> +constexpr auto enum_switch(Lambda&& lambda, string_view name, Result&& result, BinaryPredicate&& p = {}) -> detail::enable_if_t { + static_assert(std::is_invocable_r_v, "magic_enum::enum_switch requires bool(char, char) invocable predicate."); + using D = std::decay_t; + static_assert(detail::has_hash, "magic_enum::enum_switch requires no defined MAGIC_ENUM_NO_HASH"); + + if (const auto v = enum_cast(name, std::forward(p))) { + return enum_switch(std::forward(lambda), *v, std::forward(result)); + } + return std::forward(result); +} + +template +constexpr auto enum_switch(Lambda&& lambda, underlying_type_t value) -> detail::enable_if_t { + using D = std::decay_t; + static_assert(detail::has_hash, "magic_enum::enum_switch requires no defined MAGIC_ENUM_NO_HASH"); + + if (const auto v = enum_cast(value)) { + return enum_switch(std::forward(lambda), *v); + } + return detail::default_result_type_lambda(); +} + +template +constexpr auto enum_switch(Lambda&& lambda, underlying_type_t value, Result&& result) -> detail::enable_if_t { + using D = std::decay_t; + static_assert(detail::has_hash, "magic_enum::enum_switch requires no defined MAGIC_ENUM_NO_HASH"); + + if (const auto v = enum_cast(value)) { + return enum_switch(std::forward(lambda), *v, std::forward(result)); + } + return std::forward(result); +} + +template = 0> +constexpr auto enum_for_each(Lambda&& lambda) { + using D = std::decay_t; + static_assert(std::is_enum_v, "magic_enum::enum_for_each requires enum type."); + constexpr auto sep = std::make_index_sequence>{}; + + if constexpr (detail::all_invocable(sep)) { + return detail::for_each(std::forward(lambda), sep); + } else { + static_assert(detail::always_false_v, "magic_enum::enum_for_each requires invocable of all enum value."); + } } namespace ostream_operators { -template = 0> +template = 0> std::basic_ostream& operator<<(std::basic_ostream& os, E value) { - using D = std::decay_t; - using U = underlying_type_t; -#if defined(MAGIC_ENUM_SUPPORTED) && MAGIC_ENUM_SUPPORTED - if (const auto name = magic_enum::enum_flags_name(value); !name.empty()) { - for (const auto c : name) { - os.put(c); + using D = std::decay_t; + using U = underlying_type_t; + + if constexpr (detail::supported::value) { + if (const auto name = enum_flags_name(value); !name.empty()) { + for (const auto c : name) { + os.put(c); + } + return os; + } } - return os; - } -#endif - return (os << static_cast(value)); + return (os << static_cast(value)); } -template = 0> +template = 0> std::basic_ostream& operator<<(std::basic_ostream& os, optional value) { - return value.has_value() ? (os << value.value()) : os; + return value ? (os << *value) : os; } -} // namespace magic_enum::ostream_operators +} // namespace ostream_operators + +namespace istream_operators { + +template = 0> +std::basic_istream& operator>>(std::basic_istream& is, E& value) { + using D = std::decay_t; + + std::basic_string s; + is >> s; + if (const auto v = enum_cast(s)) { + value = *v; + } else { + is.setstate(std::basic_ios::failbit); + } + return is; +} + +} // namespace istream_operators + +namespace iostream_operators { + +using namespace ostream_operators; +using namespace istream_operators; + +} // namespace iostream_operators namespace bitwise_operators { -template = 0> +template = 0> constexpr E operator~(E rhs) noexcept { - return static_cast(~static_cast>(rhs)); + return static_cast(~static_cast>(rhs)); } -template = 0> +template = 0> constexpr E operator|(E lhs, E rhs) noexcept { - return static_cast(static_cast>(lhs) | static_cast>(rhs)); + return static_cast(static_cast>(lhs) | static_cast>(rhs)); } -template = 0> +template = 0> constexpr E operator&(E lhs, E rhs) noexcept { - return static_cast(static_cast>(lhs) & static_cast>(rhs)); + return static_cast(static_cast>(lhs) & static_cast>(rhs)); } -template = 0> +template = 0> constexpr E operator^(E lhs, E rhs) noexcept { - return static_cast(static_cast>(lhs) ^ static_cast>(rhs)); + return static_cast(static_cast>(lhs) ^ static_cast>(rhs)); } -template = 0> +template = 0> constexpr E& operator|=(E& lhs, E rhs) noexcept { - return lhs = (lhs | rhs); + return lhs = (lhs | rhs); } -template = 0> +template = 0> constexpr E& operator&=(E& lhs, E rhs) noexcept { - return lhs = (lhs & rhs); + return lhs = (lhs & rhs); } -template = 0> +template = 0> constexpr E& operator^=(E& lhs, E rhs) noexcept { - return lhs = (lhs ^ rhs); + return lhs = (lhs ^ rhs); } -} // namespace magic_enum::bitwise_operators +} // namespace bitwise_operators } // namespace magic_enum #if defined(__clang__) -# pragma clang diagnostic pop +#pragma clang diagnostic pop #elif defined(__GNUC__) -# pragma GCC diagnostic pop +#pragma GCC diagnostic pop #elif defined(_MSC_VER) -# pragma warning(pop) +#pragma warning(pop) #endif -#endif // NEARGYE_MAGIC_ENUM_HPP +#endif // NEARGYE_MAGIC_ENUM_HPP \ No newline at end of file diff --git a/LiteLoader/third-party/include/mysql/mysql.h b/LiteLoader/third-party/include/mysql/mysql.h index bf78926..4700d74 100644 --- a/LiteLoader/third-party/include/mysql/mysql.h +++ b/LiteLoader/third-party/include/mysql/mysql.h @@ -55,9 +55,9 @@ typedef uint64_t my_ulonglong; #ifndef my_socket_defined #define my_socket_defined #ifdef _WIN32 -#include +#include #ifdef WIN32_LEAN_AND_MEAN -#include +#include #endif #define my_socket SOCKET #else @@ -80,7 +80,7 @@ typedef int my_socket; #include "mysql_com.h" /* Include declarations of plug-in API */ -#include "third-party/include/mysql/mysql/client_plugin.h" // IWYU pragma: keep +#include "mysql/client_plugin.h" // IWYU pragma: keep /* The client should be able to know which version it is compiled against, diff --git a/LiteLoader/third-party/include/mysql/mysql/plugin_auth_common.h b/LiteLoader/third-party/include/mysql/mysql/plugin_auth_common.h index a219c12..b27313c 100644 --- a/LiteLoader/third-party/include/mysql/mysql/plugin_auth_common.h +++ b/LiteLoader/third-party/include/mysql/mysql/plugin_auth_common.h @@ -109,7 +109,7 @@ authenticated_as when proxy mapping should be done by the server. #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif -#include +#include #endif struct MYSQL_PLUGIN_VIO_INFO { diff --git a/LiteLoader/third-party/include/mysql/mysql_com.h b/LiteLoader/third-party/include/mysql/mysql_com.h index c7c3896..97e9798 100644 --- a/LiteLoader/third-party/include/mysql/mysql_com.h +++ b/LiteLoader/third-party/include/mysql/mysql_com.h @@ -1072,7 +1072,7 @@ struct rand_struct { }; /* Include the types here so existing UDFs can keep compiling */ -#include "third-party/include/mysql/mysql/udf_registration_types.h" +#include "mysql/udf_registration_types.h" /** @addtogroup group_cs_compresson_constants Constants when using compression diff --git a/LiteLoader/third-party/include/openssl/aes.h b/LiteLoader/third-party/include/openssl/aes.h index c1f4a2e..d0f9dfc 100644 --- a/LiteLoader/third-party/include/openssl/aes.h +++ b/LiteLoader/third-party/include/openssl/aes.h @@ -11,12 +11,12 @@ # define OPENSSL_AES_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_AES_H # endif -# include "opensslconf.h" +# include # include # ifdef __cplusplus diff --git a/LiteLoader/third-party/include/openssl/asn1.h b/LiteLoader/third-party/include/openssl/asn1.h index a8f564f..aada23d 100644 --- a/LiteLoader/third-party/include/openssl/asn1.h +++ b/LiteLoader/third-party/include/openssl/asn1.h @@ -16,21 +16,21 @@ # define OPENSSL_ASN1_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_ASN1_H # endif # include -# include "e_os2.h" -# include "opensslconf.h" -# include "bio.h" -# include "safestack.h" -# include "asn1err.h" -# include "symhacks.h" +# include +# include +# include +# include +# include +# include -# include "types.h" -# include "bn.h" +# include +# include # ifdef OPENSSL_BUILD_SHLIBCRYPTO # undef OPENSSL_EXTERN diff --git a/LiteLoader/third-party/include/openssl/asn1.h.in b/LiteLoader/third-party/include/openssl/asn1.h.in index 541b035..6d5094a 100644 --- a/LiteLoader/third-party/include/openssl/asn1.h.in +++ b/LiteLoader/third-party/include/openssl/asn1.h.in @@ -17,21 +17,21 @@ use OpenSSL::stackhash qw(generate_stack_macros); # define OPENSSL_ASN1_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_ASN1_H # endif # include -# include "e_os2.h" -# include "opensslconf.h" -# include "bio.h" -# include "safestack.h" -# include "asn1err.h" -# include "symhacks.h" +# include +# include +# include +# include +# include +# include -# include "types.h" -# include "bn.h" +# include +# include # ifdef OPENSSL_BUILD_SHLIBCRYPTO # undef OPENSSL_EXTERN diff --git a/LiteLoader/third-party/include/openssl/asn1err.h b/LiteLoader/third-party/include/openssl/asn1err.h index f6a5996..d427622 100644 --- a/LiteLoader/third-party/include/openssl/asn1err.h +++ b/LiteLoader/third-party/include/openssl/asn1err.h @@ -12,9 +12,9 @@ # define OPENSSL_ASN1ERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/asn1t.h b/LiteLoader/third-party/include/openssl/asn1t.h index 8fd2cd2..a725c53 100644 --- a/LiteLoader/third-party/include/openssl/asn1t.h +++ b/LiteLoader/third-party/include/openssl/asn1t.h @@ -16,14 +16,14 @@ # define OPENSSL_ASN1T_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_ASN1T_H # endif # include -# include "e_os2.h" -# include "asn1.h" +# include +# include # ifdef OPENSSL_BUILD_SHLIBCRYPTO # undef OPENSSL_EXTERN diff --git a/LiteLoader/third-party/include/openssl/asn1t.h.in b/LiteLoader/third-party/include/openssl/asn1t.h.in index c3b8e71..b536fe5 100644 --- a/LiteLoader/third-party/include/openssl/asn1t.h.in +++ b/LiteLoader/third-party/include/openssl/asn1t.h.in @@ -17,14 +17,14 @@ use OpenSSL::stackhash qw(generate_stack_macros); # define OPENSSL_ASN1T_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_ASN1T_H # endif # include -# include "e_os2.h" -# include "asn1.h" +# include +# include # ifdef OPENSSL_BUILD_SHLIBCRYPTO # undef OPENSSL_EXTERN diff --git a/LiteLoader/third-party/include/openssl/async.h b/LiteLoader/third-party/include/openssl/async.h index ed27715..bc27d5d 100644 --- a/LiteLoader/third-party/include/openssl/async.h +++ b/LiteLoader/third-party/include/openssl/async.h @@ -13,7 +13,7 @@ # define OPENSSL_ASYNC_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_ASYNC_H # endif @@ -28,7 +28,7 @@ #define OSSL_ASYNC_FD int #define OSSL_BAD_ASYNC_FD -1 #endif -# include "asyncerr.h" +# include # ifdef __cplusplus diff --git a/LiteLoader/third-party/include/openssl/asyncerr.h b/LiteLoader/third-party/include/openssl/asyncerr.h index 87e17ed..c093f7b 100644 --- a/LiteLoader/third-party/include/openssl/asyncerr.h +++ b/LiteLoader/third-party/include/openssl/asyncerr.h @@ -12,9 +12,9 @@ # define OPENSSL_ASYNCERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/bio.h b/LiteLoader/third-party/include/openssl/bio.h index fd247f2..0c1077e 100644 --- a/LiteLoader/third-party/include/openssl/bio.h +++ b/LiteLoader/third-party/include/openssl/bio.h @@ -15,21 +15,21 @@ # define OPENSSL_BIO_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_BIO_H # endif -# include "e_os2.h" +# include # ifndef OPENSSL_NO_STDIO # include # endif # include -# include "crypto.h" -# include "bioerr.h" -# include "core.h" +# include +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/bio.h.in b/LiteLoader/third-party/include/openssl/bio.h.in index ef0464d..651843b 100644 --- a/LiteLoader/third-party/include/openssl/bio.h.in +++ b/LiteLoader/third-party/include/openssl/bio.h.in @@ -16,21 +16,21 @@ use OpenSSL::stackhash qw(generate_stack_macros); # define OPENSSL_BIO_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_BIO_H # endif -# include "e_os2.h" +# include # ifndef OPENSSL_NO_STDIO # include # endif # include -# include "crypto.h" -# include "bioerr.h" -# include "core.h" +# include +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/bioerr.h b/LiteLoader/third-party/include/openssl/bioerr.h index 7054844..787b30a 100644 --- a/LiteLoader/third-party/include/openssl/bioerr.h +++ b/LiteLoader/third-party/include/openssl/bioerr.h @@ -12,9 +12,9 @@ # define OPENSSL_BIOERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/blowfish.h b/LiteLoader/third-party/include/openssl/blowfish.h index 3e462eb..667d642 100644 --- a/LiteLoader/third-party/include/openssl/blowfish.h +++ b/LiteLoader/third-party/include/openssl/blowfish.h @@ -11,15 +11,15 @@ # define OPENSSL_BLOWFISH_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_BLOWFISH_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_BF -# include "e_os2.h" +# include # ifdef __cplusplus extern "C" { # endif diff --git a/LiteLoader/third-party/include/openssl/bn.h b/LiteLoader/third-party/include/openssl/bn.h index d2fb707..ecd7f01 100644 --- a/LiteLoader/third-party/include/openssl/bn.h +++ b/LiteLoader/third-party/include/openssl/bn.h @@ -12,19 +12,19 @@ # define OPENSSL_BN_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_BN_H # endif -# include "e_os2.h" +# include # ifndef OPENSSL_NO_STDIO # include # endif -# include "opensslconf.h" -# include "types.h" -# include "crypto.h" -# include "bnerr.h" +# include +# include +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/bnerr.h b/LiteLoader/third-party/include/openssl/bnerr.h index bfef9d9..7c3f6ef 100644 --- a/LiteLoader/third-party/include/openssl/bnerr.h +++ b/LiteLoader/third-party/include/openssl/bnerr.h @@ -12,9 +12,9 @@ # define OPENSSL_BNERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/buffer.h b/LiteLoader/third-party/include/openssl/buffer.h index 44b423c..5773b98 100644 --- a/LiteLoader/third-party/include/openssl/buffer.h +++ b/LiteLoader/third-party/include/openssl/buffer.h @@ -11,16 +11,16 @@ # define OPENSSL_BUFFER_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_BUFFER_H # endif -# include "types.h" +# include # ifndef OPENSSL_CRYPTO_H # include # endif -# include "buffererr.h" +# include #ifdef __cplusplus diff --git a/LiteLoader/third-party/include/openssl/buffererr.h b/LiteLoader/third-party/include/openssl/buffererr.h index d53ced7..d18b1f8 100644 --- a/LiteLoader/third-party/include/openssl/buffererr.h +++ b/LiteLoader/third-party/include/openssl/buffererr.h @@ -12,9 +12,9 @@ # define OPENSSL_BUFFERERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/camellia.h b/LiteLoader/third-party/include/openssl/camellia.h index 66e83f3..88c2279 100644 --- a/LiteLoader/third-party/include/openssl/camellia.h +++ b/LiteLoader/third-party/include/openssl/camellia.h @@ -11,12 +11,12 @@ # define OPENSSL_CAMELLIA_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_CAMELLIA_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_CAMELLIA # include diff --git a/LiteLoader/third-party/include/openssl/cast.h b/LiteLoader/third-party/include/openssl/cast.h index 4830fd6..0bf217b 100644 --- a/LiteLoader/third-party/include/openssl/cast.h +++ b/LiteLoader/third-party/include/openssl/cast.h @@ -11,12 +11,12 @@ # define OPENSSL_CAST_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_CAST_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_CAST # ifdef __cplusplus diff --git a/LiteLoader/third-party/include/openssl/cmac.h b/LiteLoader/third-party/include/openssl/cmac.h index 5fe92c6..f508618 100644 --- a/LiteLoader/third-party/include/openssl/cmac.h +++ b/LiteLoader/third-party/include/openssl/cmac.h @@ -11,7 +11,7 @@ # define OPENSSL_CMAC_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_CMAC_H # endif @@ -22,7 +22,7 @@ extern "C" { # endif -# include "evp.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 /* Opaque */ diff --git a/LiteLoader/third-party/include/openssl/cmp.h b/LiteLoader/third-party/include/openssl/cmp.h index a9e5824..7f258dc 100644 --- a/LiteLoader/third-party/include/openssl/cmp.h +++ b/LiteLoader/third-party/include/openssl/cmp.h @@ -17,19 +17,19 @@ #ifndef OPENSSL_CMP_H # define OPENSSL_CMP_H -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_CMP -# include "crmf.h" -# include "cmperr.h" -# include "cmp_util.h" -# include "http.h" +# include +# include +# include +# include /* explicit #includes not strictly needed since implied by the above: */ -# include "types.h" -# include "safestack.h" -# include "x509.h" -# include "x509v3.h" +# include +# include +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/cmp.h.in b/LiteLoader/third-party/include/openssl/cmp.h.in index cfad154..b473442 100644 --- a/LiteLoader/third-party/include/openssl/cmp.h.in +++ b/LiteLoader/third-party/include/openssl/cmp.h.in @@ -18,19 +18,19 @@ use OpenSSL::stackhash qw(generate_stack_macros); #ifndef OPENSSL_CMP_H # define OPENSSL_CMP_H -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_CMP -# include "crmf.h" -# include "cmperr.h" -# include "cmp_util.h" -# include "http.h" +# include +# include +# include +# include /* explicit #includes not strictly needed since implied by the above: */ -# include "types.h" -# include "safestack.h" -# include "x509.h" -# include "x509v3.h" +# include +# include +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/cmp_util.h b/LiteLoader/third-party/include/openssl/cmp_util.h index eb2a566..9a16892 100644 --- a/LiteLoader/third-party/include/openssl/cmp_util.h +++ b/LiteLoader/third-party/include/openssl/cmp_util.h @@ -13,11 +13,11 @@ # define OPENSSL_CMP_UTIL_H # pragma once -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_CMP -# include "macros.h" -# include "trace.h" +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/cmperr.h b/LiteLoader/third-party/include/openssl/cmperr.h index 9a34abd..3a26fd0 100644 --- a/LiteLoader/third-party/include/openssl/cmperr.h +++ b/LiteLoader/third-party/include/openssl/cmperr.h @@ -12,9 +12,9 @@ # define OPENSSL_CMPERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include # ifndef OPENSSL_NO_CMP diff --git a/LiteLoader/third-party/include/openssl/cms.h b/LiteLoader/third-party/include/openssl/cms.h index ffad65c..5b907f2 100644 --- a/LiteLoader/third-party/include/openssl/cms.h +++ b/LiteLoader/third-party/include/openssl/cms.h @@ -16,17 +16,17 @@ # define OPENSSL_CMS_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_CMS_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_CMS -# include "x509.h" -# include "x509v3.h" -# include "cmserr.h" +# include +# include +# include # ifdef __cplusplus extern "C" { # endif diff --git a/LiteLoader/third-party/include/openssl/cms.h.in b/LiteLoader/third-party/include/openssl/cms.h.in index fe54fa1..da20ddf 100644 --- a/LiteLoader/third-party/include/openssl/cms.h.in +++ b/LiteLoader/third-party/include/openssl/cms.h.in @@ -17,17 +17,17 @@ use OpenSSL::stackhash qw(generate_stack_macros); # define OPENSSL_CMS_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_CMS_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_CMS -# include "x509.h" -# include "x509v3.h" -# include "cmserr.h" +# include +# include +# include # ifdef __cplusplus extern "C" { # endif diff --git a/LiteLoader/third-party/include/openssl/cmserr.h b/LiteLoader/third-party/include/openssl/cmserr.h index 4bf3b08..1c4f4c7 100644 --- a/LiteLoader/third-party/include/openssl/cmserr.h +++ b/LiteLoader/third-party/include/openssl/cmserr.h @@ -12,9 +12,9 @@ # define OPENSSL_CMSERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include # ifndef OPENSSL_NO_CMS diff --git a/LiteLoader/third-party/include/openssl/comp.h b/LiteLoader/third-party/include/openssl/comp.h index efc38a6..06ff581 100644 --- a/LiteLoader/third-party/include/openssl/comp.h +++ b/LiteLoader/third-party/include/openssl/comp.h @@ -11,16 +11,16 @@ # define OPENSSL_COMP_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_COMP_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_COMP -# include "crypto.h" -# include "comperr.h" +# include +# include # ifdef __cplusplus extern "C" { # endif diff --git a/LiteLoader/third-party/include/openssl/comperr.h b/LiteLoader/third-party/include/openssl/comperr.h index fb350d4..01dd3e6 100644 --- a/LiteLoader/third-party/include/openssl/comperr.h +++ b/LiteLoader/third-party/include/openssl/comperr.h @@ -12,9 +12,9 @@ # define OPENSSL_COMPERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include # ifndef OPENSSL_NO_COMP diff --git a/LiteLoader/third-party/include/openssl/conf.h b/LiteLoader/third-party/include/openssl/conf.h index 69a259c..07793f1 100644 --- a/LiteLoader/third-party/include/openssl/conf.h +++ b/LiteLoader/third-party/include/openssl/conf.h @@ -16,17 +16,17 @@ # define OPENSSL_CONF_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_CONF_H # endif -# include "bio.h" -# include "lhash.h" -# include "safestack.h" -# include "e_os2.h" -# include "types.h" -# include "conferr.h" +# include +# include +# include +# include +# include +# include #ifdef __cplusplus extern "C" { @@ -86,7 +86,7 @@ struct conf_method_st; typedef struct conf_method_st CONF_METHOD; # ifndef OPENSSL_NO_DEPRECATED_3_0 -# include "conftypes.h" +# include # endif /* Module definitions */ diff --git a/LiteLoader/third-party/include/openssl/conf.h.in b/LiteLoader/third-party/include/openssl/conf.h.in index b0234bf..b0bd579 100644 --- a/LiteLoader/third-party/include/openssl/conf.h.in +++ b/LiteLoader/third-party/include/openssl/conf.h.in @@ -17,17 +17,17 @@ use OpenSSL::stackhash qw(generate_stack_macros generate_lhash_macros); # define OPENSSL_CONF_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_CONF_H # endif -# include "bio.h" -# include "lhash.h" -# include "safestack.h" -# include "e_os2.h" -# include "types.h" -# include "conferr.h" +# include +# include +# include +# include +# include +# include #ifdef __cplusplus extern "C" { @@ -49,7 +49,7 @@ struct conf_method_st; typedef struct conf_method_st CONF_METHOD; # ifndef OPENSSL_NO_DEPRECATED_3_0 -# include "conftypes.h" +# include # endif /* Module definitions */ diff --git a/LiteLoader/third-party/include/openssl/conf_api.h b/LiteLoader/third-party/include/openssl/conf_api.h index 41fcdfc..ed67d57 100644 --- a/LiteLoader/third-party/include/openssl/conf_api.h +++ b/LiteLoader/third-party/include/openssl/conf_api.h @@ -11,13 +11,13 @@ # define OPENSSL_CONF_API_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_CONF_API_H # endif -# include "lhash.h" -# include "conf.h" +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/conferr.h b/LiteLoader/third-party/include/openssl/conferr.h index aedbc16..496e2e1 100644 --- a/LiteLoader/third-party/include/openssl/conferr.h +++ b/LiteLoader/third-party/include/openssl/conferr.h @@ -12,9 +12,9 @@ # define OPENSSL_CONFERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/core.h b/LiteLoader/third-party/include/openssl/core.h index 24b7c82..9683ac7 100644 --- a/LiteLoader/third-party/include/openssl/core.h +++ b/LiteLoader/third-party/include/openssl/core.h @@ -12,7 +12,7 @@ # pragma once # include -# include "types.h" +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/core_dispatch.h b/LiteLoader/third-party/include/openssl/core_dispatch.h index 9e9a57d..99fcda0 100644 --- a/LiteLoader/third-party/include/openssl/core_dispatch.h +++ b/LiteLoader/third-party/include/openssl/core_dispatch.h @@ -12,7 +12,7 @@ # pragma once # include -# include "core.h" +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/crmf.h b/LiteLoader/third-party/include/openssl/crmf.h index 5ec49b3..b2a82ed 100644 --- a/LiteLoader/third-party/include/openssl/crmf.h +++ b/LiteLoader/third-party/include/openssl/crmf.h @@ -19,17 +19,17 @@ #ifndef OPENSSL_CRMF_H # define OPENSSL_CRMF_H -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_CRMF -# include "opensslv.h" -# include "safestack.h" -# include "crmferr.h" -# include "x509v3.h" /* for GENERAL_NAME etc. */ +# include +# include +# include +# include /* for GENERAL_NAME etc. */ /* explicit #includes not strictly needed since implied by the above: */ -# include "types.h" -# include "x509.h" +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/crmf.h.in b/LiteLoader/third-party/include/openssl/crmf.h.in index dfb328e..4d37ea6 100644 --- a/LiteLoader/third-party/include/openssl/crmf.h.in +++ b/LiteLoader/third-party/include/openssl/crmf.h.in @@ -20,17 +20,17 @@ use OpenSSL::stackhash qw(generate_stack_macros); #ifndef OPENSSL_CRMF_H # define OPENSSL_CRMF_H -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_CRMF -# include "opensslv.h" -# include "safestack.h" -# include "crmferr.h" -# include "x509v3.h" /* for GENERAL_NAME etc. */ +# include +# include +# include +# include /* for GENERAL_NAME etc. */ /* explicit #includes not strictly needed since implied by the above: */ -# include "types.h" -# include "x509.h" +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/crmferr.h b/LiteLoader/third-party/include/openssl/crmferr.h index fcb5a53..b242b92 100644 --- a/LiteLoader/third-party/include/openssl/crmferr.h +++ b/LiteLoader/third-party/include/openssl/crmferr.h @@ -12,9 +12,9 @@ # define OPENSSL_CRMFERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include # ifndef OPENSSL_NO_CRMF diff --git a/LiteLoader/third-party/include/openssl/crypto.h b/LiteLoader/third-party/include/openssl/crypto.h index 0e281f7..8b82593 100644 --- a/LiteLoader/third-party/include/openssl/crypto.h +++ b/LiteLoader/third-party/include/openssl/crypto.h @@ -17,7 +17,7 @@ # define OPENSSL_CRYPTO_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_CRYPTO_H # endif @@ -25,18 +25,18 @@ # include # include -# include "e_os2.h" +# include # ifndef OPENSSL_NO_STDIO # include # endif -# include "safestack.h" -# include "opensslv.h" -# include "types.h" -# include "opensslconf.h" -# include "cryptoerr.h" -# include "core.h" +# include +# include +# include +# include +# include +# include # ifdef CHARSET_EBCDIC # include @@ -46,10 +46,10 @@ * Resolve problems on some operating systems with symbol names that clash * one way or another */ -# include "symhacks.h" +# include # ifndef OPENSSL_NO_DEPRECATED_1_1_0 -# include "opensslv.h" +# include # endif #ifdef __cplusplus diff --git a/LiteLoader/third-party/include/openssl/crypto.h.in b/LiteLoader/third-party/include/openssl/crypto.h.in index fd4b84b..7232f64 100644 --- a/LiteLoader/third-party/include/openssl/crypto.h.in +++ b/LiteLoader/third-party/include/openssl/crypto.h.in @@ -18,7 +18,7 @@ use OpenSSL::stackhash qw(generate_stack_macros); # define OPENSSL_CRYPTO_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_CRYPTO_H # endif @@ -26,18 +26,18 @@ use OpenSSL::stackhash qw(generate_stack_macros); # include # include -# include "e_os2.h" +# include # ifndef OPENSSL_NO_STDIO # include # endif -# include "safestack.h" -# include "opensslv.h" -# include "types.h" -# include "opensslconf.h" -# include "cryptoerr.h" -# include "core.h" +# include +# include +# include +# include +# include +# include # ifdef CHARSET_EBCDIC # include @@ -47,10 +47,10 @@ use OpenSSL::stackhash qw(generate_stack_macros); * Resolve problems on some operating systems with symbol names that clash * one way or another */ -# include "symhacks.h" +# include # ifndef OPENSSL_NO_DEPRECATED_1_1_0 -# include "opensslv.h" +# include # endif #ifdef __cplusplus diff --git a/LiteLoader/third-party/include/openssl/cryptoerr.h b/LiteLoader/third-party/include/openssl/cryptoerr.h index 98c3ea4..c6a04d9 100644 --- a/LiteLoader/third-party/include/openssl/cryptoerr.h +++ b/LiteLoader/third-party/include/openssl/cryptoerr.h @@ -12,9 +12,9 @@ # define OPENSSL_CRYPTOERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/cryptoerr_legacy.h b/LiteLoader/third-party/include/openssl/cryptoerr_legacy.h index b517c61..ccab33a 100644 --- a/LiteLoader/third-party/include/openssl/cryptoerr_legacy.h +++ b/LiteLoader/third-party/include/openssl/cryptoerr_legacy.h @@ -18,8 +18,8 @@ # define OPENSSL_CRYPTOERR_LEGACY_H # pragma once -# include "macros.h" -# include "symhacks.h" +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/ct.h b/LiteLoader/third-party/include/openssl/ct.h index daec60f..06c41b7 100644 --- a/LiteLoader/third-party/include/openssl/ct.h +++ b/LiteLoader/third-party/include/openssl/ct.h @@ -16,18 +16,18 @@ # define OPENSSL_CT_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_CT_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_CT -# include "types.h" -# include "safestack.h" -# include "x509.h" -# include "cterr.h" +# include +# include +# include +# include # ifdef __cplusplus extern "C" { # endif diff --git a/LiteLoader/third-party/include/openssl/ct.h.in b/LiteLoader/third-party/include/openssl/ct.h.in index bc6f29f..16086b3 100644 --- a/LiteLoader/third-party/include/openssl/ct.h.in +++ b/LiteLoader/third-party/include/openssl/ct.h.in @@ -17,18 +17,18 @@ use OpenSSL::stackhash qw(generate_stack_macros); # define OPENSSL_CT_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_CT_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_CT -# include "types.h" -# include "safestack.h" -# include "x509.h" -# include "cterr.h" +# include +# include +# include +# include # ifdef __cplusplus extern "C" { # endif diff --git a/LiteLoader/third-party/include/openssl/cterr.h b/LiteLoader/third-party/include/openssl/cterr.h index 4293cb6..935d32d 100644 --- a/LiteLoader/third-party/include/openssl/cterr.h +++ b/LiteLoader/third-party/include/openssl/cterr.h @@ -12,9 +12,9 @@ # define OPENSSL_CTERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include # ifndef OPENSSL_NO_CT diff --git a/LiteLoader/third-party/include/openssl/decoder.h b/LiteLoader/third-party/include/openssl/decoder.h index bcbf588..d4ee2cf 100644 --- a/LiteLoader/third-party/include/openssl/decoder.h +++ b/LiteLoader/third-party/include/openssl/decoder.h @@ -11,16 +11,16 @@ # define OPENSSL_DECODER_H # pragma once -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_STDIO # include # endif # include # include -# include "decodererr.h" -# include "types.h" -# include "core.h" +# include +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/decodererr.h b/LiteLoader/third-party/include/openssl/decodererr.h index 019fc63..4212a38 100644 --- a/LiteLoader/third-party/include/openssl/decodererr.h +++ b/LiteLoader/third-party/include/openssl/decodererr.h @@ -12,9 +12,9 @@ # define OPENSSL_DECODERERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/des.h b/LiteLoader/third-party/include/openssl/des.h index 73f4fb6..09798a6 100644 --- a/LiteLoader/third-party/include/openssl/des.h +++ b/LiteLoader/third-party/include/openssl/des.h @@ -11,18 +11,18 @@ # define OPENSSL_DES_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_DES_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_DES # ifdef __cplusplus extern "C" { # endif -# include "e_os2.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 typedef unsigned int DES_LONG; diff --git a/LiteLoader/third-party/include/openssl/dh.h b/LiteLoader/third-party/include/openssl/dh.h index 771c2e0..b97871e 100644 --- a/LiteLoader/third-party/include/openssl/dh.h +++ b/LiteLoader/third-party/include/openssl/dh.h @@ -11,13 +11,13 @@ # define OPENSSL_DH_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_DH_H # endif -# include "opensslconf.h" -# include "types.h" +# include +# include # ifdef __cplusplus extern "C" { @@ -80,13 +80,13 @@ int EVP_PKEY_CTX_get0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **ukm); # define EVP_PKEY_DH_KDF_X9_42 2 # ifndef OPENSSL_NO_DH -# include "e_os2.h" -# include "bio.h" -# include "asn1.h" +# include +# include +# include # ifndef OPENSSL_NO_DEPRECATED_1_1_0 -# include "bn.h" +# include # endif -# include "dherr.h" +# include # ifndef OPENSSL_DH_MAX_MODULUS_BITS # define OPENSSL_DH_MAX_MODULUS_BITS 10000 diff --git a/LiteLoader/third-party/include/openssl/dherr.h b/LiteLoader/third-party/include/openssl/dherr.h index 7fb0c3f..5d2a762 100644 --- a/LiteLoader/third-party/include/openssl/dherr.h +++ b/LiteLoader/third-party/include/openssl/dherr.h @@ -12,9 +12,9 @@ # define OPENSSL_DHERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include # ifndef OPENSSL_NO_DH diff --git a/LiteLoader/third-party/include/openssl/dsa.h b/LiteLoader/third-party/include/openssl/dsa.h index 8cc98c8..5c0e4cd 100644 --- a/LiteLoader/third-party/include/openssl/dsa.h +++ b/LiteLoader/third-party/include/openssl/dsa.h @@ -11,13 +11,13 @@ # define OPENSSL_DSA_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_DSA_H # endif -# include "opensslconf.h" -# include "types.h" +# include +# include # ifdef __cplusplus extern "C" { @@ -42,15 +42,15 @@ int EVP_PKEY_CTX_set_dsa_paramgen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md); # define EVP_PKEY_CTRL_DSA_PARAMGEN_MD (EVP_PKEY_ALG_CTRL + 3) # ifndef OPENSSL_NO_DSA -# include "e_os2.h" -# include "asn1.h" -# include "bio.h" -# include "crypto.h" -# include "bn.h" +# include +# include +# include +# include +# include # ifndef OPENSSL_NO_DEPRECATED_1_1_0 -# include "dh.h" +# include # endif -# include "dsaerr.h" +# include # ifndef OPENSSL_DSA_MAX_MODULUS_BITS # define OPENSSL_DSA_MAX_MODULUS_BITS 10000 diff --git a/LiteLoader/third-party/include/openssl/dsaerr.h b/LiteLoader/third-party/include/openssl/dsaerr.h index 9e6339a..5f0ca8d 100644 --- a/LiteLoader/third-party/include/openssl/dsaerr.h +++ b/LiteLoader/third-party/include/openssl/dsaerr.h @@ -12,9 +12,9 @@ # define OPENSSL_DSAERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include # ifndef OPENSSL_NO_DSA diff --git a/LiteLoader/third-party/include/openssl/dtls1.h b/LiteLoader/third-party/include/openssl/dtls1.h index 34f0349..5dc6b54 100644 --- a/LiteLoader/third-party/include/openssl/dtls1.h +++ b/LiteLoader/third-party/include/openssl/dtls1.h @@ -11,18 +11,18 @@ # define OPENSSL_DTLS1_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_DTLS1_H # endif -# include "prov_ssl.h" +# include #ifdef __cplusplus extern "C" { #endif -#include "opensslconf.h" +#include /* DTLS*_VERSION constants are defined in prov_ssl.h */ # ifndef OPENSSL_NO_DEPRECATED_3_0 diff --git a/LiteLoader/third-party/include/openssl/e_os2.h b/LiteLoader/third-party/include/openssl/e_os2.h index e4994ba..6728909 100644 --- a/LiteLoader/third-party/include/openssl/e_os2.h +++ b/LiteLoader/third-party/include/openssl/e_os2.h @@ -11,12 +11,12 @@ # define OPENSSL_E_OS2_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_E_OS2_H # endif -# include "opensslconf.h" +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/ebcdic.h b/LiteLoader/third-party/include/openssl/ebcdic.h index 95e5957..e0ae1aa 100644 --- a/LiteLoader/third-party/include/openssl/ebcdic.h +++ b/LiteLoader/third-party/include/openssl/ebcdic.h @@ -11,7 +11,7 @@ # define OPENSSL_EBCDIC_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_EBCDIC_H # endif diff --git a/LiteLoader/third-party/include/openssl/ec.h b/LiteLoader/third-party/include/openssl/ec.h index e7b9092..44d7193 100644 --- a/LiteLoader/third-party/include/openssl/ec.h +++ b/LiteLoader/third-party/include/openssl/ec.h @@ -12,13 +12,13 @@ # define OPENSSL_EC_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_EC_H # endif -# include "opensslconf.h" -# include "types.h" +# include +# include # include @@ -89,18 +89,18 @@ typedef enum { const char *OSSL_EC_curve_nid2name(int nid); # ifndef OPENSSL_NO_EC -# include "asn1.h" -# include "symhacks.h" +# include +# include # ifndef OPENSSL_NO_DEPRECATED_1_1_0 -# include "bn.h" +# include # endif -# include "ecerr.h" +# include # ifndef OPENSSL_ECC_MAX_FIELD_BITS # define OPENSSL_ECC_MAX_FIELD_BITS 661 # endif -# include "params.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 typedef struct ec_method_st EC_METHOD; # endif diff --git a/LiteLoader/third-party/include/openssl/ecdh.h b/LiteLoader/third-party/include/openssl/ecdh.h index c48602e..56bd4cc 100644 --- a/LiteLoader/third-party/include/openssl/ecdh.h +++ b/LiteLoader/third-party/include/openssl/ecdh.h @@ -7,4 +7,4 @@ * https://www.openssl.org/source/license.html */ -#include "ec.h" +#include diff --git a/LiteLoader/third-party/include/openssl/ecdsa.h b/LiteLoader/third-party/include/openssl/ecdsa.h index c48602e..56bd4cc 100644 --- a/LiteLoader/third-party/include/openssl/ecdsa.h +++ b/LiteLoader/third-party/include/openssl/ecdsa.h @@ -7,4 +7,4 @@ * https://www.openssl.org/source/license.html */ -#include "ec.h" +#include diff --git a/LiteLoader/third-party/include/openssl/ecerr.h b/LiteLoader/third-party/include/openssl/ecerr.h index b63448a..46405ac 100644 --- a/LiteLoader/third-party/include/openssl/ecerr.h +++ b/LiteLoader/third-party/include/openssl/ecerr.h @@ -12,9 +12,9 @@ # define OPENSSL_ECERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include # ifndef OPENSSL_NO_EC diff --git a/LiteLoader/third-party/include/openssl/encoder.h b/LiteLoader/third-party/include/openssl/encoder.h index 331379d..c37a6f1 100644 --- a/LiteLoader/third-party/include/openssl/encoder.h +++ b/LiteLoader/third-party/include/openssl/encoder.h @@ -11,16 +11,16 @@ # define OPENSSL_ENCODER_H # pragma once -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_STDIO # include # endif # include # include -# include "encodererr.h" -# include "types.h" -# include "core.h" +# include +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/encodererr.h b/LiteLoader/third-party/include/openssl/encodererr.h index 5bc2bf6..5e318b1 100644 --- a/LiteLoader/third-party/include/openssl/encodererr.h +++ b/LiteLoader/third-party/include/openssl/encodererr.h @@ -12,9 +12,9 @@ # define OPENSSL_ENCODERERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/engine.h b/LiteLoader/third-party/include/openssl/engine.h index 738a9f0..c965800 100644 --- a/LiteLoader/third-party/include/openssl/engine.h +++ b/LiteLoader/third-party/include/openssl/engine.h @@ -12,28 +12,28 @@ # define OPENSSL_ENGINE_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_ENGINE_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_ENGINE # ifndef OPENSSL_NO_DEPRECATED_1_1_0 -# include "bn.h" -# include "rsa.h" -# include "dsa.h" -# include "dh.h" -# include "ec.h" -# include "rand.h" -# include "ui.h" -# include "err.h" +# include +# include +# include +# include +# include +# include +# include +# include # endif -# include "types.h" -# include "symhacks.h" -# include "x509.h" -# include "engineerr.h" +# include +# include +# include +# include # ifdef __cplusplus extern "C" { # endif diff --git a/LiteLoader/third-party/include/openssl/engineerr.h b/LiteLoader/third-party/include/openssl/engineerr.h index 33b8e10..d439b68 100644 --- a/LiteLoader/third-party/include/openssl/engineerr.h +++ b/LiteLoader/third-party/include/openssl/engineerr.h @@ -12,9 +12,9 @@ # define OPENSSL_ENGINEERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include # ifndef OPENSSL_NO_ENGINE diff --git a/LiteLoader/third-party/include/openssl/err.h b/LiteLoader/third-party/include/openssl/err.h index 20c082b..3c7299d 100644 --- a/LiteLoader/third-party/include/openssl/err.h +++ b/LiteLoader/third-party/include/openssl/err.h @@ -13,22 +13,22 @@ # define OPENSSL_ERR_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_ERR_H # endif -# include "e_os2.h" +# include # ifndef OPENSSL_NO_STDIO # include # include # endif -# include "types.h" -# include "bio.h" -# include "lhash.h" -# include "cryptoerr_legacy.h" +# include +# include +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/err.h.in b/LiteLoader/third-party/include/openssl/err.h.in index 223e5b5..7ca0b97 100644 --- a/LiteLoader/third-party/include/openssl/err.h.in +++ b/LiteLoader/third-party/include/openssl/err.h.in @@ -15,22 +15,22 @@ use OpenSSL::stackhash qw(generate_lhash_macros); # define OPENSSL_ERR_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_ERR_H # endif -# include "e_os2.h" +# include # ifndef OPENSSL_NO_STDIO # include # include # endif -# include "types.h" -# include "bio.h" -# include "lhash.h" -# include "cryptoerr_legacy.h" +# include +# include +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/ess.h b/LiteLoader/third-party/include/openssl/ess.h index a3617f7..dad596a 100644 --- a/LiteLoader/third-party/include/openssl/ess.h +++ b/LiteLoader/third-party/include/openssl/ess.h @@ -16,11 +16,11 @@ # define OPENSSL_ESS_H # pragma once -# include "opensslconf.h" +# include -# include "safestack.h" -# include "x509.h" -# include "esserr.h" +# include +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/ess.h.in b/LiteLoader/third-party/include/openssl/ess.h.in index 9f4d732..d1a685b 100644 --- a/LiteLoader/third-party/include/openssl/ess.h.in +++ b/LiteLoader/third-party/include/openssl/ess.h.in @@ -17,11 +17,11 @@ use OpenSSL::stackhash qw(generate_stack_macros); # define OPENSSL_ESS_H # pragma once -# include "opensslconf.h" +# include -# include "safestack.h" -# include "x509.h" -# include "esserr.h" +# include +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/esserr.h b/LiteLoader/third-party/include/openssl/esserr.h index 3d9e92e..165ce7c 100644 --- a/LiteLoader/third-party/include/openssl/esserr.h +++ b/LiteLoader/third-party/include/openssl/esserr.h @@ -12,9 +12,9 @@ # define OPENSSL_ESSERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include /* * ESS reason codes. diff --git a/LiteLoader/third-party/include/openssl/evp.h b/LiteLoader/third-party/include/openssl/evp.h index f02e102..49e8e1d 100644 --- a/LiteLoader/third-party/include/openssl/evp.h +++ b/LiteLoader/third-party/include/openssl/evp.h @@ -11,7 +11,7 @@ # define OPENSSL_EVP_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_ENVELOPE_H # endif @@ -22,14 +22,14 @@ # include # endif -# include "opensslconf.h" -# include "types.h" -# include "core.h" -# include "core_dispatch.h" -# include "symhacks.h" -# include "bio.h" -# include "evperr.h" -# include "params.h" +# include +# include +# include +# include +# include +# include +# include +# include # define EVP_MAX_MD_SIZE 64/* longest known is SHA512 */ # define EVP_MAX_KEY_LENGTH 64 @@ -40,7 +40,7 @@ /* Default PKCS#5 iteration count */ # define PKCS5_DEFAULT_ITER 2048 -# include "objects.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define EVP_PK_RSA 0x0001 diff --git a/LiteLoader/third-party/include/openssl/evperr.h b/LiteLoader/third-party/include/openssl/evperr.h index 5b4cbd7..a5053f6 100644 --- a/LiteLoader/third-party/include/openssl/evperr.h +++ b/LiteLoader/third-party/include/openssl/evperr.h @@ -12,9 +12,9 @@ # define OPENSSL_EVPERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/hmac.h b/LiteLoader/third-party/include/openssl/hmac.h index 310df1b..f9e1bff 100644 --- a/LiteLoader/third-party/include/openssl/hmac.h +++ b/LiteLoader/third-party/include/openssl/hmac.h @@ -11,14 +11,14 @@ # define OPENSSL_HMAC_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_HMAC_H # endif -# include "opensslconf.h" +# include -# include "evp.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HMAC_MAX_MD_CBLOCK 200 /* Deprecated */ diff --git a/LiteLoader/third-party/include/openssl/http.h b/LiteLoader/third-party/include/openssl/http.h index b110926..f7ab214 100644 --- a/LiteLoader/third-party/include/openssl/http.h +++ b/LiteLoader/third-party/include/openssl/http.h @@ -12,11 +12,11 @@ # define OPENSSL_HTTP_H # pragma once -# include "opensslconf.h" +# include -# include "bio.h" -# include "asn1.h" -# include "conf.h" +# include +# include +# include # ifdef __cplusplus diff --git a/LiteLoader/third-party/include/openssl/httperr.h b/LiteLoader/third-party/include/openssl/httperr.h index 1d2b784..ee08959 100644 --- a/LiteLoader/third-party/include/openssl/httperr.h +++ b/LiteLoader/third-party/include/openssl/httperr.h @@ -12,9 +12,9 @@ # define OPENSSL_HTTPERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/idea.h b/LiteLoader/third-party/include/openssl/idea.h index 3f6c3bb..1f9bb3b 100644 --- a/LiteLoader/third-party/include/openssl/idea.h +++ b/LiteLoader/third-party/include/openssl/idea.h @@ -11,12 +11,12 @@ # define OPENSSL_IDEA_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_IDEA_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_IDEA # ifdef __cplusplus diff --git a/LiteLoader/third-party/include/openssl/kdf.h b/LiteLoader/third-party/include/openssl/kdf.h index 88aef7d..0983230 100644 --- a/LiteLoader/third-party/include/openssl/kdf.h +++ b/LiteLoader/third-party/include/openssl/kdf.h @@ -11,15 +11,15 @@ # define OPENSSL_KDF_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_KDF_H # endif # include # include -# include "types.h" -# include "core.h" +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/kdferr.h b/LiteLoader/third-party/include/openssl/kdferr.h index 3a0d7c5..963d766 100644 --- a/LiteLoader/third-party/include/openssl/kdferr.h +++ b/LiteLoader/third-party/include/openssl/kdferr.h @@ -11,6 +11,6 @@ # define OPENSSL_KDFERR_H # pragma once -#include "cryptoerr_legacy.h" +#include #endif /* !defined(OPENSSL_KDFERR_H) */ diff --git a/LiteLoader/third-party/include/openssl/lhash.h b/LiteLoader/third-party/include/openssl/lhash.h index 184e65d..39dd625 100644 --- a/LiteLoader/third-party/include/openssl/lhash.h +++ b/LiteLoader/third-party/include/openssl/lhash.h @@ -17,13 +17,13 @@ # define OPENSSL_LHASH_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_LHASH_H # endif -# include "e_os2.h" -# include "bio.h" +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/lhash.h.in b/LiteLoader/third-party/include/openssl/lhash.h.in index 895afff..febefa3 100644 --- a/LiteLoader/third-party/include/openssl/lhash.h.in +++ b/LiteLoader/third-party/include/openssl/lhash.h.in @@ -19,13 +19,13 @@ use OpenSSL::stackhash qw(generate_lhash_macros); # define OPENSSL_LHASH_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_LHASH_H # endif -# include "e_os2.h" -# include "bio.h" +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/macros.h b/LiteLoader/third-party/include/openssl/macros.h index 3a3ea51..a6bc3f1 100644 --- a/LiteLoader/third-party/include/openssl/macros.h +++ b/LiteLoader/third-party/include/openssl/macros.h @@ -11,8 +11,8 @@ # define OPENSSL_MACROS_H # pragma once -#include "opensslconf.h" -#include "opensslv.h" +#include +#include /* Helper macros for CPP string composition */ diff --git a/LiteLoader/third-party/include/openssl/md2.h b/LiteLoader/third-party/include/openssl/md2.h index c24fd5a..5d4cb77 100644 --- a/LiteLoader/third-party/include/openssl/md2.h +++ b/LiteLoader/third-party/include/openssl/md2.h @@ -11,12 +11,12 @@ # define OPENSSL_MD2_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_MD2_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_MD2 # include diff --git a/LiteLoader/third-party/include/openssl/md4.h b/LiteLoader/third-party/include/openssl/md4.h index e3e7a86..6c150a6 100644 --- a/LiteLoader/third-party/include/openssl/md4.h +++ b/LiteLoader/third-party/include/openssl/md4.h @@ -11,15 +11,15 @@ # define OPENSSL_MD4_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_MD4_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_MD4 -# include "e_os2.h" +# include # include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/md5.h b/LiteLoader/third-party/include/openssl/md5.h index 62ecaf4..77a5773 100644 --- a/LiteLoader/third-party/include/openssl/md5.h +++ b/LiteLoader/third-party/include/openssl/md5.h @@ -11,15 +11,15 @@ # define OPENSSL_MD5_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_MD5_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_MD5 -# include "e_os2.h" +# include # include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/mdc2.h b/LiteLoader/third-party/include/openssl/mdc2.h index d85b817..5a7ee28 100644 --- a/LiteLoader/third-party/include/openssl/mdc2.h +++ b/LiteLoader/third-party/include/openssl/mdc2.h @@ -11,16 +11,16 @@ # define OPENSSL_MDC2_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_MDC2_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_MDC2 # include -# include "des.h" +# include # ifdef __cplusplus extern "C" { # endif diff --git a/LiteLoader/third-party/include/openssl/modes.h b/LiteLoader/third-party/include/openssl/modes.h index 2559b17..e190799 100644 --- a/LiteLoader/third-party/include/openssl/modes.h +++ b/LiteLoader/third-party/include/openssl/modes.h @@ -11,13 +11,13 @@ # define OPENSSL_MODES_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_MODES_H # endif # include -# include "types.h" +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/objects.h b/LiteLoader/third-party/include/openssl/objects.h index 76b51b6..9ea91c2 100644 --- a/LiteLoader/third-party/include/openssl/objects.h +++ b/LiteLoader/third-party/include/openssl/objects.h @@ -11,15 +11,15 @@ # define OPENSSL_OBJECTS_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_OBJECTS_H # endif -# include "obj_mac.h" -# include "bio.h" -# include "asn1.h" -# include "objectserr.h" +# include +# include +# include +# include # define OBJ_NAME_TYPE_UNDEF 0x00 # define OBJ_NAME_TYPE_MD_METH 0x01 diff --git a/LiteLoader/third-party/include/openssl/objectserr.h b/LiteLoader/third-party/include/openssl/objectserr.h index 3397706..585217f 100644 --- a/LiteLoader/third-party/include/openssl/objectserr.h +++ b/LiteLoader/third-party/include/openssl/objectserr.h @@ -12,9 +12,9 @@ # define OPENSSL_OBJECTSERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/ocsp.h b/LiteLoader/third-party/include/openssl/ocsp.h index 00c9af1..5688381 100644 --- a/LiteLoader/third-party/include/openssl/ocsp.h +++ b/LiteLoader/third-party/include/openssl/ocsp.h @@ -16,14 +16,14 @@ # define OPENSSL_OCSP_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_OCSP_H # endif -# include "opensslconf.h" -# include "http.h" -# include "asn1.h" +# include +# include +# include /* * These definitions are outside the OPENSSL_NO_OCSP guard because although for @@ -59,10 +59,10 @@ # ifndef OPENSSL_NO_OCSP -# include "x509.h" -# include "x509v3.h" -# include "safestack.h" -# include "ocsperr.h" +# include +# include +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/ocsp.h.in b/LiteLoader/third-party/include/openssl/ocsp.h.in index e7823ab..e2cc271 100644 --- a/LiteLoader/third-party/include/openssl/ocsp.h.in +++ b/LiteLoader/third-party/include/openssl/ocsp.h.in @@ -17,14 +17,14 @@ use OpenSSL::stackhash qw(generate_stack_macros); # define OPENSSL_OCSP_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_OCSP_H # endif -# include "opensslconf.h" -# include "http.h" -# include "asn1.h" +# include +# include +# include /* * These definitions are outside the OPENSSL_NO_OCSP guard because although for @@ -60,10 +60,10 @@ use OpenSSL::stackhash qw(generate_stack_macros); # ifndef OPENSSL_NO_OCSP -# include "x509.h" -# include "x509v3.h" -# include "safestack.h" -# include "ocsperr.h" +# include +# include +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/ocsperr.h b/LiteLoader/third-party/include/openssl/ocsperr.h index 1cd3950..46a0523 100644 --- a/LiteLoader/third-party/include/openssl/ocsperr.h +++ b/LiteLoader/third-party/include/openssl/ocsperr.h @@ -12,9 +12,9 @@ # define OPENSSL_OCSPERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include # ifndef OPENSSL_NO_OCSP diff --git a/LiteLoader/third-party/include/openssl/opensslconf.h b/LiteLoader/third-party/include/openssl/opensslconf.h index b17c9b3..1e83371 100644 --- a/LiteLoader/third-party/include/openssl/opensslconf.h +++ b/LiteLoader/third-party/include/openssl/opensslconf.h @@ -11,7 +11,7 @@ # define OPENSSL_OPENSSLCONF_H # pragma once -# include "configuration.h" -# include "macros.h" +# include +# include #endif /* OPENSSL_OPENSSLCONF_H */ diff --git a/LiteLoader/third-party/include/openssl/opensslv.h b/LiteLoader/third-party/include/openssl/opensslv.h index 27e9e34..028ae24 100644 --- a/LiteLoader/third-party/include/openssl/opensslv.h +++ b/LiteLoader/third-party/include/openssl/opensslv.h @@ -106,7 +106,7 @@ extern "C" { } # endif -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_OPENSSLV_H # endif diff --git a/LiteLoader/third-party/include/openssl/opensslv.h.in b/LiteLoader/third-party/include/openssl/opensslv.h.in index 72af878..3f47a2a 100644 --- a/LiteLoader/third-party/include/openssl/opensslv.h.in +++ b/LiteLoader/third-party/include/openssl/opensslv.h.in @@ -105,7 +105,7 @@ extern "C" { } # endif -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_OPENSSLV_H # endif diff --git a/LiteLoader/third-party/include/openssl/ossl_typ.h b/LiteLoader/third-party/include/openssl/ossl_typ.h index 301027a..82a5898 100644 --- a/LiteLoader/third-party/include/openssl/ossl_typ.h +++ b/LiteLoader/third-party/include/openssl/ossl_typ.h @@ -13,4 +13,4 @@ * This header file only exists for compatibility reasons with older * applications which #include . */ -# include "types.h" +# include diff --git a/LiteLoader/third-party/include/openssl/param_build.h b/LiteLoader/third-party/include/openssl/param_build.h index 977e8e2..f29fdb2 100644 --- a/LiteLoader/third-party/include/openssl/param_build.h +++ b/LiteLoader/third-party/include/openssl/param_build.h @@ -12,8 +12,8 @@ # define OPENSSL_PARAM_BUILD_H # pragma once -# include "params.h" -# include "types.h" +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/params.h b/LiteLoader/third-party/include/openssl/params.h index 98a2686..d75eab0 100644 --- a/LiteLoader/third-party/include/openssl/params.h +++ b/LiteLoader/third-party/include/openssl/params.h @@ -12,8 +12,8 @@ # define OPENSSL_PARAMS_H # pragma once -# include "core.h" -# include "bn.h" +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/pem.h b/LiteLoader/third-party/include/openssl/pem.h index 078d3b1..80940df 100644 --- a/LiteLoader/third-party/include/openssl/pem.h +++ b/LiteLoader/third-party/include/openssl/pem.h @@ -11,17 +11,17 @@ # define OPENSSL_PEM_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_PEM_H # endif -# include "e_os2.h" -# include "bio.h" -# include "safestack.h" -# include "evp.h" -# include "x509.h" -# include "pemerr.h" +# include +# include +# include +# include +# include +# include #ifdef __cplusplus extern "C" { @@ -431,7 +431,7 @@ int PEM_def_callback(char *buf, int num, int rwflag, void *userdata); void PEM_proc_type(char *buf, int type); void PEM_dek_info(char *buf, const char *type, int len, const char *str); -# include "symhacks.h" +# include DECLARE_PEM_rw(X509, X509) DECLARE_PEM_rw(X509_AUX, X509) diff --git a/LiteLoader/third-party/include/openssl/pem2.h b/LiteLoader/third-party/include/openssl/pem2.h index 9167648..a8a5325 100644 --- a/LiteLoader/third-party/include/openssl/pem2.h +++ b/LiteLoader/third-party/include/openssl/pem2.h @@ -11,9 +11,9 @@ # define OPENSSL_PEM2_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_PEM2_H # endif -# include "pemerr.h" +# include #endif diff --git a/LiteLoader/third-party/include/openssl/pemerr.h b/LiteLoader/third-party/include/openssl/pemerr.h index 3be7d9b..18f6d9e 100644 --- a/LiteLoader/third-party/include/openssl/pemerr.h +++ b/LiteLoader/third-party/include/openssl/pemerr.h @@ -12,9 +12,9 @@ # define OPENSSL_PEMERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/pkcs12.h b/LiteLoader/third-party/include/openssl/pkcs12.h index b7e787d..f0da086 100644 --- a/LiteLoader/third-party/include/openssl/pkcs12.h +++ b/LiteLoader/third-party/include/openssl/pkcs12.h @@ -16,15 +16,15 @@ # define OPENSSL_PKCS12_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_PKCS12_H # endif -# include "bio.h" -# include "core.h" -# include "x509.h" -# include "pkcs12err.h" +# include +# include +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/pkcs12.h.in b/LiteLoader/third-party/include/openssl/pkcs12.h.in index 67bf243..c98eebf 100644 --- a/LiteLoader/third-party/include/openssl/pkcs12.h.in +++ b/LiteLoader/third-party/include/openssl/pkcs12.h.in @@ -17,15 +17,15 @@ use OpenSSL::stackhash qw(generate_stack_macros); # define OPENSSL_PKCS12_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_PKCS12_H # endif -# include "bio.h" -# include "core.h" -# include "x509.h" -# include "pkcs12err.h" +# include +# include +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/pkcs12err.h b/LiteLoader/third-party/include/openssl/pkcs12err.h index 82f18c3..933c832 100644 --- a/LiteLoader/third-party/include/openssl/pkcs12err.h +++ b/LiteLoader/third-party/include/openssl/pkcs12err.h @@ -12,9 +12,9 @@ # define OPENSSL_PKCS12ERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/pkcs7.h b/LiteLoader/third-party/include/openssl/pkcs7.h index 13c9ca5..097d2db 100644 --- a/LiteLoader/third-party/include/openssl/pkcs7.h +++ b/LiteLoader/third-party/include/openssl/pkcs7.h @@ -16,18 +16,18 @@ # define OPENSSL_PKCS7_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_PKCS7_H # endif -# include "asn1.h" -# include "bio.h" -# include "e_os2.h" +# include +# include +# include -# include "symhacks.h" -# include "types.h" -# include "pkcs7err.h" +# include +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/pkcs7.h.in b/LiteLoader/third-party/include/openssl/pkcs7.h.in index 9435492..f5c55a3 100644 --- a/LiteLoader/third-party/include/openssl/pkcs7.h.in +++ b/LiteLoader/third-party/include/openssl/pkcs7.h.in @@ -17,18 +17,18 @@ use OpenSSL::stackhash qw(generate_stack_macros); # define OPENSSL_PKCS7_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_PKCS7_H # endif -# include "asn1.h" -# include "bio.h" -# include "e_os2.h" +# include +# include +# include -# include "symhacks.h" -# include "types.h" -# include "pkcs7err.h" +# include +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/pkcs7err.h b/LiteLoader/third-party/include/openssl/pkcs7err.h index 4e5425d..ceb1a50 100644 --- a/LiteLoader/third-party/include/openssl/pkcs7err.h +++ b/LiteLoader/third-party/include/openssl/pkcs7err.h @@ -12,9 +12,9 @@ # define OPENSSL_PKCS7ERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/proverr.h b/LiteLoader/third-party/include/openssl/proverr.h index 9b04d3b..ad67a8f 100644 --- a/LiteLoader/third-party/include/openssl/proverr.h +++ b/LiteLoader/third-party/include/openssl/proverr.h @@ -12,9 +12,9 @@ # define OPENSSL_PROVERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/provider.h b/LiteLoader/third-party/include/openssl/provider.h index f9f5d7f..dc86ff5 100644 --- a/LiteLoader/third-party/include/openssl/provider.h +++ b/LiteLoader/third-party/include/openssl/provider.h @@ -11,7 +11,7 @@ # define OPENSSL_PROVIDER_H # pragma once -# include "core.h" +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/rand.h b/LiteLoader/third-party/include/openssl/rand.h index 9b466cc..ad3054f 100644 --- a/LiteLoader/third-party/include/openssl/rand.h +++ b/LiteLoader/third-party/include/openssl/rand.h @@ -11,16 +11,16 @@ # define OPENSSL_RAND_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_RAND_H # endif # include -# include "types.h" -# include "e_os2.h" -# include "randerr.h" -# include "evp.h" +# include +# include +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/randerr.h b/LiteLoader/third-party/include/openssl/randerr.h index c5eb789..b5e08e4 100644 --- a/LiteLoader/third-party/include/openssl/randerr.h +++ b/LiteLoader/third-party/include/openssl/randerr.h @@ -12,9 +12,9 @@ # define OPENSSL_RANDERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/rc2.h b/LiteLoader/third-party/include/openssl/rc2.h index 7c4d68d..ff633fd 100644 --- a/LiteLoader/third-party/include/openssl/rc2.h +++ b/LiteLoader/third-party/include/openssl/rc2.h @@ -11,12 +11,12 @@ # define OPENSSL_RC2_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_RC2_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_RC2 # ifdef __cplusplus diff --git a/LiteLoader/third-party/include/openssl/rc4.h b/LiteLoader/third-party/include/openssl/rc4.h index f3f3188..600b288 100644 --- a/LiteLoader/third-party/include/openssl/rc4.h +++ b/LiteLoader/third-party/include/openssl/rc4.h @@ -11,12 +11,12 @@ # define OPENSSL_RC4_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_RC4_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_RC4 # include diff --git a/LiteLoader/third-party/include/openssl/rc5.h b/LiteLoader/third-party/include/openssl/rc5.h index c73507d..de83352 100644 --- a/LiteLoader/third-party/include/openssl/rc5.h +++ b/LiteLoader/third-party/include/openssl/rc5.h @@ -11,12 +11,12 @@ # define OPENSSL_RC5_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_RC5_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_RC5 # ifdef __cplusplus diff --git a/LiteLoader/third-party/include/openssl/ripemd.h b/LiteLoader/third-party/include/openssl/ripemd.h index e4386a0..900ee31 100644 --- a/LiteLoader/third-party/include/openssl/ripemd.h +++ b/LiteLoader/third-party/include/openssl/ripemd.h @@ -11,15 +11,15 @@ # define OPENSSL_RIPEMD_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_RIPEMD_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_RMD160 -# include "e_os2.h" +# include # include # define RIPEMD160_DIGEST_LENGTH 20 diff --git a/LiteLoader/third-party/include/openssl/rsa.h b/LiteLoader/third-party/include/openssl/rsa.h index 36afa5a..a55c972 100644 --- a/LiteLoader/third-party/include/openssl/rsa.h +++ b/LiteLoader/third-party/include/openssl/rsa.h @@ -11,22 +11,22 @@ # define OPENSSL_RSA_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_RSA_H # endif -# include "opensslconf.h" +# include -# include "asn1.h" -# include "bio.h" -# include "crypto.h" -# include "types.h" +# include +# include +# include +# include # ifndef OPENSSL_NO_DEPRECATED_1_1_0 -# include "bn.h" +# include # endif -# include "rsaerr.h" -# include "safestack.h" +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/rsaerr.h b/LiteLoader/third-party/include/openssl/rsaerr.h index a02094b..c58463c 100644 --- a/LiteLoader/third-party/include/openssl/rsaerr.h +++ b/LiteLoader/third-party/include/openssl/rsaerr.h @@ -12,9 +12,9 @@ # define OPENSSL_RSAERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/safestack.h b/LiteLoader/third-party/include/openssl/safestack.h index adbf8cc..159ccf2 100644 --- a/LiteLoader/third-party/include/openssl/safestack.h +++ b/LiteLoader/third-party/include/openssl/safestack.h @@ -16,13 +16,13 @@ # define OPENSSL_SAFESTACK_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_SAFESTACK_H # endif -# include "stack.h" -# include "e_os2.h" +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/safestack.h.in b/LiteLoader/third-party/include/openssl/safestack.h.in index 2836d48..6b36607 100644 --- a/LiteLoader/third-party/include/openssl/safestack.h.in +++ b/LiteLoader/third-party/include/openssl/safestack.h.in @@ -19,13 +19,13 @@ use OpenSSL::stackhash qw(generate_stack_string_macros # define OPENSSL_SAFESTACK_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_SAFESTACK_H # endif -# include "stack.h" -# include "e_os2.h" +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/seed.h b/LiteLoader/third-party/include/openssl/seed.h index 1934b91..edb218a 100644 --- a/LiteLoader/third-party/include/openssl/seed.h +++ b/LiteLoader/third-party/include/openssl/seed.h @@ -36,16 +36,16 @@ # define OPENSSL_SEED_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_SEED_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_SEED -# include "e_os2.h" -# include "crypto.h" +# include +# include # include # ifdef __cplusplus diff --git a/LiteLoader/third-party/include/openssl/self_test.h b/LiteLoader/third-party/include/openssl/self_test.h index 9542e75..ee4949e 100644 --- a/LiteLoader/third-party/include/openssl/self_test.h +++ b/LiteLoader/third-party/include/openssl/self_test.h @@ -11,7 +11,7 @@ # define OPENSSL_SELF_TEST_H # pragma once -# include "core.h" /* OSSL_CALLBACK */ +# include /* OSSL_CALLBACK */ # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/sha.h b/LiteLoader/third-party/include/openssl/sha.h index 167189e..6e65a04 100644 --- a/LiteLoader/third-party/include/openssl/sha.h +++ b/LiteLoader/third-party/include/openssl/sha.h @@ -11,12 +11,12 @@ # define OPENSSL_SHA_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_SHA_H # endif -# include "e_os2.h" +# include # include # ifdef __cplusplus diff --git a/LiteLoader/third-party/include/openssl/srp.h b/LiteLoader/third-party/include/openssl/srp.h index f595c03..a86fa5d 100644 --- a/LiteLoader/third-party/include/openssl/srp.h +++ b/LiteLoader/third-party/include/openssl/srp.h @@ -20,19 +20,19 @@ # define OPENSSL_SRP_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_SRP_H # endif -#include "opensslconf.h" +#include #ifndef OPENSSL_NO_SRP # include # include -# include "safestack.h" -# include "bn.h" -# include "crypto.h" +# include +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/srp.h.in b/LiteLoader/third-party/include/openssl/srp.h.in index 815fe94..dfbe845 100644 --- a/LiteLoader/third-party/include/openssl/srp.h.in +++ b/LiteLoader/third-party/include/openssl/srp.h.in @@ -21,19 +21,19 @@ use OpenSSL::stackhash qw(generate_stack_macros); # define OPENSSL_SRP_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_SRP_H # endif -#include "opensslconf.h" +#include #ifndef OPENSSL_NO_SRP # include # include -# include "safestack.h" -# include "bn.h" -# include "crypto.h" +# include +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/srtp.h b/LiteLoader/third-party/include/openssl/srtp.h index a91171b..d64606e 100644 --- a/LiteLoader/third-party/include/openssl/srtp.h +++ b/LiteLoader/third-party/include/openssl/srtp.h @@ -17,12 +17,12 @@ # define OPENSSL_SRTP_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_D1_SRTP_H # endif -# include "ssl.h" +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/ssl.h b/LiteLoader/third-party/include/openssl/ssl.h index cfa7a02..441b818 100644 --- a/LiteLoader/third-party/include/openssl/ssl.h +++ b/LiteLoader/third-party/include/openssl/ssl.h @@ -18,30 +18,30 @@ # define OPENSSL_SSL_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_SSL_H # endif -# include "e_os2.h" -# include "opensslconf.h" -# include "comp.h" -# include "bio.h" +# include +# include +# include +# include # ifndef OPENSSL_NO_DEPRECATED_1_1_0 -# include "x509.h" -# include "crypto.h" -# include "buffer.h" +# include +# include +# include # endif -# include "lhash.h" -# include "pem.h" -# include "hmac.h" -# include "async.h" +# include +# include +# include +# include -# include "safestack.h" -# include "symhacks.h" -# include "ct.h" -# include "sslerr.h" -# include "prov_ssl.h" +# include +# include +# include +# include +# include #ifdef __cplusplus extern "C" { @@ -960,11 +960,11 @@ uint32_t SSL_get_recv_max_early_data(const SSL *s); } #endif -# include "ssl2.h" -# include "ssl3.h" -# include "tls1.h" /* This is mostly sslv3 with a few tweaks */ -# include "dtls1.h" /* Datagram TLS */ -# include "srtp.h" /* Support for the use_srtp extension */ +# include +# include +# include /* This is mostly sslv3 with a few tweaks */ +# include /* Datagram TLS */ +# include /* Support for the use_srtp extension */ #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/ssl.h.in b/LiteLoader/third-party/include/openssl/ssl.h.in index 4c5f201..105b4a4 100644 --- a/LiteLoader/third-party/include/openssl/ssl.h.in +++ b/LiteLoader/third-party/include/openssl/ssl.h.in @@ -19,30 +19,30 @@ use OpenSSL::stackhash qw(generate_stack_macros generate_const_stack_macros); # define OPENSSL_SSL_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_SSL_H # endif -# include "e_os2.h" -# include "opensslconf.h" -# include "comp.h" -# include "bio.h" +# include +# include +# include +# include # ifndef OPENSSL_NO_DEPRECATED_1_1_0 -# include "x509.h" -# include "crypto.h" -# include "buffer.h" +# include +# include +# include # endif -# include "lhash.h" -# include "pem.h" -# include "hmac.h" -# include "async.h" +# include +# include +# include +# include -# include "safestack.h" -# include "symhacks.h" -# include "ct.h" -# include "sslerr.h" -# include "prov_ssl.h" +# include +# include +# include +# include +# include #ifdef __cplusplus extern "C" { @@ -937,11 +937,11 @@ uint32_t SSL_get_recv_max_early_data(const SSL *s); } #endif -# include "ssl2.h" -# include "ssl3.h" -# include "tls1.h" /* This is mostly sslv3 with a few tweaks */ -# include "dtls1.h" /* Datagram TLS */ -# include "srtp.h" /* Support for the use_srtp extension */ +# include +# include +# include /* This is mostly sslv3 with a few tweaks */ +# include /* Datagram TLS */ +# include /* Support for the use_srtp extension */ #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/ssl2.h b/LiteLoader/third-party/include/openssl/ssl2.h index 40f95af..428ead0 100644 --- a/LiteLoader/third-party/include/openssl/ssl2.h +++ b/LiteLoader/third-party/include/openssl/ssl2.h @@ -11,7 +11,7 @@ # define OPENSSL_SSL2_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_SSL2_H # endif diff --git a/LiteLoader/third-party/include/openssl/ssl3.h b/LiteLoader/third-party/include/openssl/ssl3.h index 2b8cc01..49bd51f 100644 --- a/LiteLoader/third-party/include/openssl/ssl3.h +++ b/LiteLoader/third-party/include/openssl/ssl3.h @@ -12,15 +12,15 @@ # define OPENSSL_SSL3_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_SSL3_H # endif -# include "comp.h" -# include "buffer.h" -# include "evp.h" -# include "ssl.h" +# include +# include +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/sslerr.h b/LiteLoader/third-party/include/openssl/sslerr.h index 3ac4478..a4746d7 100644 --- a/LiteLoader/third-party/include/openssl/sslerr.h +++ b/LiteLoader/third-party/include/openssl/sslerr.h @@ -12,9 +12,9 @@ # define OPENSSL_SSLERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "sslerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/sslerr_legacy.h b/LiteLoader/third-party/include/openssl/sslerr_legacy.h index f79b1fd..ccf6d3b 100644 --- a/LiteLoader/third-party/include/openssl/sslerr_legacy.h +++ b/LiteLoader/third-party/include/openssl/sslerr_legacy.h @@ -18,8 +18,8 @@ # define OPENSSL_SSLERR_LEGACY_H # pragma once -# include "macros.h" -# include "symhacks.h" +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/stack.h b/LiteLoader/third-party/include/openssl/stack.h index 9a4ab85..f0c5c54 100644 --- a/LiteLoader/third-party/include/openssl/stack.h +++ b/LiteLoader/third-party/include/openssl/stack.h @@ -11,7 +11,7 @@ # define OPENSSL_STACK_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_STACK_H # endif diff --git a/LiteLoader/third-party/include/openssl/store.h b/LiteLoader/third-party/include/openssl/store.h index 22f9ff3..3c1445e 100644 --- a/LiteLoader/third-party/include/openssl/store.h +++ b/LiteLoader/third-party/include/openssl/store.h @@ -11,15 +11,15 @@ # define OPENSSL_STORE_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_OSSL_STORE_H # endif # include -# include "types.h" -# include "pem.h" -# include "storeerr.h" +# include +# include +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/storeerr.h b/LiteLoader/third-party/include/openssl/storeerr.h index ddcdee0..00529c8 100644 --- a/LiteLoader/third-party/include/openssl/storeerr.h +++ b/LiteLoader/third-party/include/openssl/storeerr.h @@ -12,9 +12,9 @@ # define OPENSSL_STOREERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/symhacks.h b/LiteLoader/third-party/include/openssl/symhacks.h index d3ef404..816f8f9 100644 --- a/LiteLoader/third-party/include/openssl/symhacks.h +++ b/LiteLoader/third-party/include/openssl/symhacks.h @@ -11,12 +11,12 @@ # define OPENSSL_SYMHACKS_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_SYMHACKS_H # endif -# include "e_os2.h" +# include /* Case insensitive linking causes problems.... */ # if defined(OPENSSL_SYS_VMS) diff --git a/LiteLoader/third-party/include/openssl/tls1.h b/LiteLoader/third-party/include/openssl/tls1.h index 131a30b..d6e9331 100644 --- a/LiteLoader/third-party/include/openssl/tls1.h +++ b/LiteLoader/third-party/include/openssl/tls1.h @@ -13,14 +13,14 @@ # define OPENSSL_TLS1_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_TLS1_H # endif -# include "buffer.h" -# include "x509.h" -# include "prov_ssl.h" +# include +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/trace.h b/LiteLoader/third-party/include/openssl/trace.h index 720707b..2820013 100644 --- a/LiteLoader/third-party/include/openssl/trace.h +++ b/LiteLoader/third-party/include/openssl/trace.h @@ -13,7 +13,7 @@ # include -# include "bio.h" +# include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/ts.h b/LiteLoader/third-party/include/openssl/ts.h index a865462..5136e4e 100644 --- a/LiteLoader/third-party/include/openssl/ts.h +++ b/LiteLoader/third-party/include/openssl/ts.h @@ -11,31 +11,31 @@ # define OPENSSL_TS_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_TS_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_TS -# include "symhacks.h" -# include "buffer.h" -# include "evp.h" -# include "bio.h" -# include "asn1.h" -# include "safestack.h" -# include "rsa.h" -# include "dsa.h" -# include "dh.h" -# include "tserr.h" -# include "ess.h" +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include # ifdef __cplusplus extern "C" { # endif -# include "x509.h" -# include "x509v3.h" +# include +# include typedef struct TS_msg_imprint_st TS_MSG_IMPRINT; typedef struct TS_req_st TS_REQ; diff --git a/LiteLoader/third-party/include/openssl/tserr.h b/LiteLoader/third-party/include/openssl/tserr.h index 042fe1f..e1b943e 100644 --- a/LiteLoader/third-party/include/openssl/tserr.h +++ b/LiteLoader/third-party/include/openssl/tserr.h @@ -12,9 +12,9 @@ # define OPENSSL_TSERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include # ifndef OPENSSL_NO_TS diff --git a/LiteLoader/third-party/include/openssl/txt_db.h b/LiteLoader/third-party/include/openssl/txt_db.h index 4450204..af169a3 100644 --- a/LiteLoader/third-party/include/openssl/txt_db.h +++ b/LiteLoader/third-party/include/openssl/txt_db.h @@ -11,15 +11,15 @@ # define OPENSSL_TXT_DB_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_TXT_DB_H # endif -# include "opensslconf.h" -# include "bio.h" -# include "safestack.h" -# include "lhash.h" +# include +# include +# include +# include # define DB_ERROR_OK 0 # define DB_ERROR_MALLOC 1 diff --git a/LiteLoader/third-party/include/openssl/types.h b/LiteLoader/third-party/include/openssl/types.h index 3cd9838..de9f166 100644 --- a/LiteLoader/third-party/include/openssl/types.h +++ b/LiteLoader/third-party/include/openssl/types.h @@ -17,9 +17,9 @@ extern "C" { # endif -# include "e_os2.h" -# include "safestack.h" -# include "macros.h" +# include +# include +# include typedef struct ossl_provider_st OSSL_PROVIDER; /* Provider Object */ diff --git a/LiteLoader/third-party/include/openssl/ui.h b/LiteLoader/third-party/include/openssl/ui.h index c8caaaf..835b0eb 100644 --- a/LiteLoader/third-party/include/openssl/ui.h +++ b/LiteLoader/third-party/include/openssl/ui.h @@ -16,20 +16,20 @@ # define OPENSSL_UI_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_UI_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_DEPRECATED_1_1_0 -# include "crypto.h" +# include # endif -# include "safestack.h" -# include "pem.h" -# include "types.h" -# include "uierr.h" +# include +# include +# include +# include /* For compatibility reasons, the macro OPENSSL_NO_UI is currently retained */ # ifndef OPENSSL_NO_DEPRECATED_3_0 diff --git a/LiteLoader/third-party/include/openssl/ui.h.in b/LiteLoader/third-party/include/openssl/ui.h.in index 37ca806..eb9a580 100644 --- a/LiteLoader/third-party/include/openssl/ui.h.in +++ b/LiteLoader/third-party/include/openssl/ui.h.in @@ -17,20 +17,20 @@ use OpenSSL::stackhash qw(generate_stack_macros); # define OPENSSL_UI_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_UI_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_DEPRECATED_1_1_0 -# include "crypto.h" +# include # endif -# include "safestack.h" -# include "pem.h" -# include "types.h" -# include "uierr.h" +# include +# include +# include +# include /* For compatibility reasons, the macro OPENSSL_NO_UI is currently retained */ # ifndef OPENSSL_NO_DEPRECATED_3_0 diff --git a/LiteLoader/third-party/include/openssl/uierr.h b/LiteLoader/third-party/include/openssl/uierr.h index b092a82..473b04e 100644 --- a/LiteLoader/third-party/include/openssl/uierr.h +++ b/LiteLoader/third-party/include/openssl/uierr.h @@ -12,9 +12,9 @@ # define OPENSSL_UIERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/whrlpool.h b/LiteLoader/third-party/include/openssl/whrlpool.h index 741d7a3..05ba463 100644 --- a/LiteLoader/third-party/include/openssl/whrlpool.h +++ b/LiteLoader/third-party/include/openssl/whrlpool.h @@ -11,15 +11,15 @@ # define OPENSSL_WHRLPOOL_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_WHRLPOOL_H # endif -# include "opensslconf.h" +# include # ifndef OPENSSL_NO_WHIRLPOOL -# include "e_os2.h" +# include # include # ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/x509.h b/LiteLoader/third-party/include/openssl/x509.h index 63f5ccd..eda5d70 100644 --- a/LiteLoader/third-party/include/openssl/x509.h +++ b/LiteLoader/third-party/include/openssl/x509.h @@ -17,29 +17,29 @@ # define OPENSSL_X509_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_X509_H # endif -# include "e_os2.h" -# include "types.h" -# include "symhacks.h" -# include "buffer.h" -# include "evp.h" -# include "bio.h" -# include "asn1.h" -# include "safestack.h" -# include "ec.h" +# include +# include +# include +# include +# include +# include +# include +# include +# include # ifndef OPENSSL_NO_DEPRECATED_1_1_0 -# include "rsa.h" -# include "dsa.h" -# include "dh.h" +# include +# include +# include # endif -# include "sha.h" -# include "x509err.h" +# include +# include #ifdef __cplusplus extern "C" { @@ -476,8 +476,8 @@ typedef struct SCRYPT_PARAMS_st { } #endif -# include "x509_vfy.h" -# include "pkcs7.h" +# include +# include #ifdef __cplusplus extern "C" { @@ -552,7 +552,7 @@ int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, X509 *X509_load_http(const char *url, BIO *bio, BIO *rbio, int timeout); X509_CRL *X509_CRL_load_http(const char *url, BIO *bio, BIO *rbio, int timeout); # ifndef OPENSSL_NO_DEPRECATED_3_0 -# include "http.h" /* OSSL_HTTP_REQ_CTX_nbio_d2i */ +# include /* OSSL_HTTP_REQ_CTX_nbio_d2i */ # define X509_http_nbio(rctx, pcert) \ OSSL_HTTP_REQ_CTX_nbio_d2i(rctx, pcert, ASN1_ITEM_rptr(X509)) # define X509_CRL_http_nbio(rctx, pcrl) \ diff --git a/LiteLoader/third-party/include/openssl/x509.h.in b/LiteLoader/third-party/include/openssl/x509.h.in index d90d422..3ef741f 100644 --- a/LiteLoader/third-party/include/openssl/x509.h.in +++ b/LiteLoader/third-party/include/openssl/x509.h.in @@ -18,29 +18,29 @@ use OpenSSL::stackhash qw(generate_stack_macros); # define OPENSSL_X509_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_X509_H # endif -# include "e_os2.h" -# include "types.h" -# include "symhacks.h" -# include "buffer.h" -# include "evp.h" -# include "bio.h" -# include "asn1.h" -# include "safestack.h" -# include "ec.h" +# include +# include +# include +# include +# include +# include +# include +# include +# include # ifndef OPENSSL_NO_DEPRECATED_1_1_0 -# include "rsa.h" -# include "dsa.h" -# include "dh.h" +# include +# include +# include # endif -# include "sha.h" -# include "x509err.h" +# include +# include #ifdef __cplusplus extern "C" { @@ -282,8 +282,8 @@ typedef struct SCRYPT_PARAMS_st { } #endif -# include "x509_vfy.h" -# include "pkcs7.h" +# include +# include #ifdef __cplusplus extern "C" { @@ -358,7 +358,7 @@ int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, X509 *X509_load_http(const char *url, BIO *bio, BIO *rbio, int timeout); X509_CRL *X509_CRL_load_http(const char *url, BIO *bio, BIO *rbio, int timeout); # ifndef OPENSSL_NO_DEPRECATED_3_0 -# include "http.h" /* OSSL_HTTP_REQ_CTX_nbio_d2i */ +# include /* OSSL_HTTP_REQ_CTX_nbio_d2i */ # define X509_http_nbio(rctx, pcert) \ OSSL_HTTP_REQ_CTX_nbio_d2i(rctx, pcert, ASN1_ITEM_rptr(X509)) # define X509_CRL_http_nbio(rctx, pcrl) \ diff --git a/LiteLoader/third-party/include/openssl/x509_vfy.h b/LiteLoader/third-party/include/openssl/x509_vfy.h index 72a2ab1..e04df0d 100644 --- a/LiteLoader/third-party/include/openssl/x509_vfy.h +++ b/LiteLoader/third-party/include/openssl/x509_vfy.h @@ -16,7 +16,7 @@ # define OPENSSL_X509_VFY_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_X509_VFY_H # endif @@ -28,11 +28,11 @@ # include # endif -# include "opensslconf.h" -# include "lhash.h" -# include "bio.h" -# include "crypto.h" -# include "symhacks.h" +# include +# include +# include +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/x509_vfy.h.in b/LiteLoader/third-party/include/openssl/x509_vfy.h.in index cd99884..80f18bd 100644 --- a/LiteLoader/third-party/include/openssl/x509_vfy.h.in +++ b/LiteLoader/third-party/include/openssl/x509_vfy.h.in @@ -17,7 +17,7 @@ use OpenSSL::stackhash qw(generate_stack_macros); # define OPENSSL_X509_VFY_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_X509_VFY_H # endif @@ -26,14 +26,14 @@ use OpenSSL::stackhash qw(generate_stack_macros); * Protect against recursion, x509.h and x509_vfy.h each include the other. */ # ifndef OPENSSL_X509_H -# include "x509.h" +# include # endif -# include "opensslconf.h" -# include "lhash.h" -# include "bio.h" -# include "crypto.h" -# include "symhacks.h" +# include +# include +# include +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/x509err.h b/LiteLoader/third-party/include/openssl/x509err.h index 5e776bc..a56facd 100644 --- a/LiteLoader/third-party/include/openssl/x509err.h +++ b/LiteLoader/third-party/include/openssl/x509err.h @@ -12,9 +12,9 @@ # define OPENSSL_X509ERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/openssl/x509v3.h b/LiteLoader/third-party/include/openssl/x509v3.h index 25866cf..78c390b 100644 --- a/LiteLoader/third-party/include/openssl/x509v3.h +++ b/LiteLoader/third-party/include/openssl/x509v3.h @@ -16,15 +16,15 @@ # define OPENSSL_X509V3_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_X509V3_H # endif -# include "bio.h" -# include "x509.h" -# include "conf.h" -# include "x509v3err.h" +# include +# include +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/x509v3.h.in b/LiteLoader/third-party/include/openssl/x509v3.h.in index 77f6c05..d00a66a 100644 --- a/LiteLoader/third-party/include/openssl/x509v3.h.in +++ b/LiteLoader/third-party/include/openssl/x509v3.h.in @@ -17,15 +17,15 @@ use OpenSSL::stackhash qw(generate_stack_macros); # define OPENSSL_X509V3_H # pragma once -# include "macros.h" +# include # ifndef OPENSSL_NO_DEPRECATED_3_0 # define HEADER_X509V3_H # endif -# include "bio.h" -# include "x509.h" -# include "conf.h" -# include "x509v3err.h" +# include +# include +# include +# include #ifdef __cplusplus extern "C" { diff --git a/LiteLoader/third-party/include/openssl/x509v3err.h b/LiteLoader/third-party/include/openssl/x509v3err.h index 05701a6..1ae3a56 100644 --- a/LiteLoader/third-party/include/openssl/x509v3err.h +++ b/LiteLoader/third-party/include/openssl/x509v3err.h @@ -12,9 +12,9 @@ # define OPENSSL_X509V3ERR_H # pragma once -# include "opensslconf.h" -# include "symhacks.h" -# include "cryptoerr_legacy.h" +# include +# include +# include diff --git a/LiteLoader/third-party/include/parallel_hashmap/meminfo.h b/LiteLoader/third-party/include/parallel_hashmap/meminfo.h index 877ced8..872f3c6 100644 --- a/LiteLoader/third-party/include/parallel_hashmap/meminfo.h +++ b/LiteLoader/third-party/include/parallel_hashmap/meminfo.h @@ -10,7 +10,7 @@ #endif #ifdef SPP_WIN - #include + #include #include #undef min #undef max diff --git a/LiteLoader/third-party/src/nbt-cpp/nbt.cpp b/LiteLoader/third-party/src/nbt-cpp/nbt.cpp index 0a93f5e..bb8c651 100644 --- a/LiteLoader/third-party/src/nbt-cpp/nbt.cpp +++ b/LiteLoader/third-party/src/nbt-cpp/nbt.cpp @@ -1,5 +1,6 @@ #include "nbt_internal.hpp" +#include #include #include #include @@ -262,7 +263,7 @@ tag_id deduce_tag(std::istream & input) { } if (std::isdigit(a) || a == '-' || a == '+') { std::string buffer(&a, 1); - tag_id deduced; + tag_id deduced = static_cast(-1); for (;;) { char b = cheof(input); buffer.push_back(b); @@ -577,7 +578,7 @@ std::unique_ptr end_list_tag::read_content(std::istream & input) { } else { char c = cheof(input); if (c != ']') - throw std::runtime_error("']' expected, got "+c); + throw std::runtime_error(std::string("']' expected, got ") + c); } return std::make_unique(); } @@ -801,8 +802,8 @@ tag_list_tag compound_list_tag::as_tags() { void read_compound_text(std::istream & input, tags::compound_tag & compound, const context & ctxt) { skip_space(input); - char a = cheof(input); - if (a != '{') + char start_char = cheof(input); + if (start_char != '{') throw std::runtime_error("failed to open compound"); for (;;) { tag_id key_type = deduce_tag(input); @@ -822,19 +823,19 @@ void read_compound_text(std::istream & input, tags::compound_tag & compound, con std::string key = tags::read_string(input, ctxt); //std::cout << key << std::endl; skip_space(input); - char a = cheof(input); - if (a != ':') - throw std::runtime_error(std::string("key-value delimiter expected, got ") + a); + char next_char = cheof(input); + if (next_char != ':') + throw std::runtime_error(std::string("key-value delimiter expected, got ") + next_char); tag_id value_type = deduce_tag(input); if (value_type == tag_id::tag_end) throw std::runtime_error(std::string("value expected")); compound.value.emplace(std::move(key), tags::read(value_type, input)); skip_space(input); - a = cheof(input); - if (a == '}') + next_char = cheof(input); + if (next_char == '}') return; - if (a != ',' && a != ';') - throw std::runtime_error(std::string("next tag or end expected, got ") + a); + if (next_char != ',' && next_char != ';') + throw std::runtime_error(std::string("next tag or end expected, got ") + next_char); } } diff --git a/LiteLoader/third-party/src/nbt-cpp/nbt_internal.hpp b/LiteLoader/third-party/src/nbt-cpp/nbt_internal.hpp index b708761..f7568ad 100644 --- a/LiteLoader/third-party/src/nbt-cpp/nbt_internal.hpp +++ b/LiteLoader/third-party/src/nbt-cpp/nbt_internal.hpp @@ -1,7 +1,7 @@ #ifndef NBT_INTERNAL_HEAD_BFGUDYHGVWCEARSTYJGHI #define NBT_INTERNAL_HEAD_BFGUDYHGVWCEARSTYJGHI -#include "../../../Header/third-party/nbt-cpp/nbt.hpp" +#include namespace nbt {