Core/Utils: Modernize Types and Tuples utils - use constexpr variables instead of structs

* Also remove unneccessary tuple type list wrapping in packet utilities
This commit is contained in:
Shauren
2026-03-06 00:51:07 +01:00
parent 88fe0f40be
commit b63e55323b
6 changed files with 76 additions and 84 deletions

View File

@@ -18,7 +18,6 @@
#include "Timezone.h"
#include "Hash.h"
#include "MapUtils.h"
#include "Tuples.h"
#include <algorithm>
#include <array>
#include <unordered_map>
@@ -170,7 +169,7 @@ std::string GetSystemZoneName()
std::string_view FindClosestClientSupportedTimezone(std::string_view currentTimezone, Minutes currentTimezoneOffset)
{
// try exact match
auto itr = std::ranges::find(_clientSupportedTimezones, currentTimezone, Trinity::TupleElement<1>);
auto itr = std::ranges::find(_clientSupportedTimezones, currentTimezone, Trinity::Containers::MapValue);
if (itr != _clientSupportedTimezones.end())
return itr->second;

View File

@@ -15,48 +15,42 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Tuples_h__
#define Tuples_h__
#ifndef TRINITYCORE_TUPLES_H
#define TRINITYCORE_TUPLES_H
#include <tuple>
namespace Trinity
{
template <typename T, typename Tuple>
struct has_type;
template <typename... Ts>
constexpr bool is_tuple_v = false;
template <typename... Ts>
constexpr bool is_tuple_v<std::tuple<Ts...>> = true;
template <typename... Ts>
using is_tuple_t = std::bool_constant<is_tuple_v<Ts...>>;
template <typename T, typename... Us>
struct has_type<T, std::tuple<Us...>> : std::disjunction<std::is_same<T, Us>...>
{
};
constexpr bool tuple_has_type_v = false;
template <typename T, typename... Us>
constexpr bool has_type_v = has_type<T, Us...>::value;
constexpr bool tuple_has_type_v<T, std::tuple<Us...>> = std::disjunction_v<std::is_same<T, Us>...>;
template<typename>
struct is_tuple : std::false_type
{
};
template<typename... Ts>
struct is_tuple<std::tuple<Ts...>> : std::true_type
{
};
template<typename... Ts>
constexpr bool is_tuple_v = is_tuple<Ts...>::value;
template <typename T, typename... Us>
using tuple_has_type_t = std::bool_constant<tuple_has_type_v<T, Us...>>;
namespace Impl
{
template <class T, class Tuple, size_t... I>
T* new_from_tuple(Tuple&& args, std::index_sequence<I...>)
inline T* new_from_tuple(Tuple&& args, std::index_sequence<I...>)
{
return new T(std::get<I>(std::forward<Tuple>(args))...);
}
}
template<class T, class Tuple>
[[nodiscard]] T* new_from_tuple(Tuple&& args)
template <class T, class Tuple>
[[nodiscard]] inline T* new_from_tuple(Tuple&& args)
{
return Impl::new_from_tuple<T>(std::forward<Tuple>(args), std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Tuple>>>{});
}
@@ -65,4 +59,4 @@ namespace Trinity
inline constexpr auto TupleElement = []<typename Tuple>(Tuple&& tuple) constexpr -> decltype(auto) { return std::get<I>(std::forward<Tuple>(tuple)); };
}
#endif // Tuples_h__
#endif // TRINITYCORE_TUPLES_H

View File

@@ -15,54 +15,56 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Types_h__
#define Types_h__
#ifndef TRINITYCORE_TYPES_H
#define TRINITYCORE_TYPES_H
#include <type_traits>
namespace Trinity
{
// end "iterator" tag for find_type_if
struct find_type_end;
template<template<typename...> typename Check, typename... Ts>
struct find_type_if;
template<template<typename...> typename Check>
struct find_type_if<Check>
template <bool HasType, typename T>
struct find_type_result
{
using type = find_type_end;
static constexpr bool has_type = HasType;
using type = T;
};
template<template<typename...> typename Check, typename T1, typename... Ts>
struct find_type_if<Check, T1, Ts...> : std::conditional_t<Check<T1>::value, std::type_identity<T1>, find_type_if<Check, Ts...>>
template <typename T>
struct find_type_result<false, T>
{
static constexpr bool has_type = false;
};
namespace Impl
{
template <template <typename> typename Check, typename T, typename... Ts>
consteval auto find_type_in_list_if_impl()
{
if constexpr (Check<T>::value)
return find_type_result<true, T>();
else if constexpr (sizeof...(Ts) == 0)
return find_type_result<false, void>();
else
return find_type_in_list_if_impl<Check, Ts...>();
}
}
/*
Utility to find a type matching predicate (Check) in a given type list (Ts)
Evaluates to first type matching predicate or find_type_end
Evaluates to Trinity::find_type_result
Check must be a type that contains static bool ::value, _v aliases don't work
template<typename... Ts>
struct Example
{
using TupleArg = Trinity::find_type_if_t<Trinity::is_tuple, Ts...>;
using Example1 = Trinity::find_type_in_list_if<Trinity::is_tuple, int, std::string, std::tuple<int, int, int>, char>;
Example1::has_type == true; // Example1::type is Trinity::find_type_result<true, std::tuple<int, int, int>>
bool HasTuple()
{
return !std::is_same_v<TupleArg, Trinity::find_type_end>;
}
};
Example<int, std::string, std::tuple<int, int, int>, char> example;
example.HasTuple() == true; // TupleArg is std::tuple<int, int, int>
Example<int, std::string, char> example2;
example2.HasTuple() == false; // TupleArg is Trinity::find_type_end
using Example2 = Trinity::find_type_in_list_if<Trinity::is_tuple, int, std::string, char>;
Example1::has_type == false; // Example2::type is not defined
*/
template<template<typename...> typename Check, typename... Ts>
using find_type_if_t = typename find_type_if<Check, Ts...>::type;
using find_type_in_list_if = decltype(Impl::find_type_in_list_if_impl<Check, Ts...>());
template <typename T, typename... Us>
constexpr bool has_type_in_list_v = std::disjunction_v<std::is_same<T, Us>...>;
template <typename T>
struct dependant_false { static constexpr bool value = false; };
@@ -71,4 +73,4 @@ namespace Trinity
constexpr bool dependant_false_v = dependant_false<T>::value;
}
#endif // Types_h__
#endif // TRINITYCORE_TYPES_H

View File

@@ -24,7 +24,7 @@
*/
#include "Define.h"
#include <type_traits>
#include "Types.h"
template <template <typename> typename UnderlyingContainer, typename... Types>
struct TypeListContainerStorage
@@ -63,7 +63,7 @@ struct TypeListContainer
TypeListContainerStorage<UnderlyingContainer, Types...> Data;
template <typename ObjectType>
static constexpr bool TypeExists = std::disjunction_v<std::is_same<ObjectType, Types>...>;
static constexpr bool TypeExists = Trinity::has_type_in_list_v<ObjectType, Types...>;
template <typename ObjectType>
using ValueType = typename UnderlyingContainer<ObjectType>::ValueType;

View File

@@ -45,25 +45,28 @@ char const* WorldPackets::InvalidHyperlinkException::GetReasonText(Reason reason
}
}
bool WorldPackets::Strings::Utf8::Validate(std::string_view value)
void WorldPackets::Strings::ByteSize::Validate(std::string_view value, std::size_t maxSize)
{
if (std::size_t size = value.size(); size > maxSize)
OnInvalidArraySize(size, maxSize);
}
void WorldPackets::Strings::Utf8::Validate(std::string_view value)
{
if (!utf8::is_valid(value.begin(), value.end()))
throw InvalidUtf8ValueException(value);
return true;
}
bool WorldPackets::Strings::Hyperlinks::Validate(std::string_view value)
void WorldPackets::Strings::Hyperlinks::Validate(std::string_view value)
{
if (!Trinity::Hyperlinks::CheckAllLinks(value))
throw InvalidHyperlinkException(value, InvalidHyperlinkException::Malformed);
return true;
}
bool WorldPackets::Strings::NoHyperlinks::Validate(std::string_view value)
void WorldPackets::Strings::NoHyperlinks::Validate(std::string_view value)
{
if (value.find('|') != std::string::npos)
throw InvalidHyperlinkException(value, InvalidHyperlinkException::NotAllowed);
return true;
}
void WorldPackets::OnInvalidArraySize(std::size_t requestedSize, std::size_t sizeLimit)

View File

@@ -20,7 +20,7 @@
#include "ByteBuffer.h"
#include "Duration.h"
#include "Tuples.h"
#include "Types.h"
#include <short_alloc/short_alloc.h>
#include <string_view>
#include <ctime>
@@ -65,24 +65,19 @@ namespace WorldPackets
namespace Strings
{
struct RawBytes { static bool Validate(std::string_view /*value*/) { return true; } };
template<std::size_t MaxBytesWithoutNullTerminator>
struct ByteSize { static bool Validate(std::string_view value) { return value.size() <= MaxBytesWithoutNullTerminator; } };
struct Utf8 { static bool Validate(std::string_view value); };
struct Hyperlinks { static bool Validate(std::string_view value); };
struct NoHyperlinks { static bool Validate(std::string_view value); };
struct RawBytes { static void Validate(std::string_view /*value*/) { } };
struct ByteSize { static void Validate(std::string_view value, std::size_t maxSize); };
struct Utf8 { static void Validate(std::string_view value); };
struct Hyperlinks { static void Validate(std::string_view value); };
struct NoHyperlinks { static void Validate(std::string_view value); };
}
/**
* Utility class for automated prevention of invalid strings in client packets
*/
template<std::size_t MaxBytesWithoutNullTerminator, typename... Validators>
template <std::size_t MaxBytesWithoutNullTerminator, typename... Validators>
class String
{
using ValidatorList = std::conditional_t<!Trinity::has_type<Strings::RawBytes, std::tuple<Validators...>>::value,
std::tuple<Strings::ByteSize<MaxBytesWithoutNullTerminator>, Strings::Utf8, Validators...>,
std::tuple<Strings::ByteSize<MaxBytesWithoutNullTerminator>, Validators...>>;
public:
bool empty() const { return _storage.empty(); }
std::size_t length() const { return _storage.length(); }
@@ -132,15 +127,14 @@ namespace WorldPackets
}
private:
static bool Validate(std::string_view value)
static void Validate(std::string_view value)
{
return ValidateNth(value, std::make_index_sequence<std::tuple_size_v<ValidatorList>>{});
}
Strings::ByteSize::Validate(value, MaxBytesWithoutNullTerminator);
template<std::size_t... indexes>
static bool ValidateNth(std::string_view value, std::index_sequence<indexes...>)
{
return (std::tuple_element_t<indexes, ValidatorList>::Validate(value) && ...);
if constexpr (!Trinity::has_type_in_list_v<Strings::RawBytes, Validators...> && !Trinity::has_type_in_list_v<Strings::Utf8, Validators...>)
Strings::Utf8::Validate(value);
(Validators::Validate(value), ...);
}
std::string _storage;