mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-13 03:32:28 -04:00
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:
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user