Core/Commands: Modernize string parsing for EXACT_SEQUENCE command arguments

(cherry picked from commit de5f2ff798)
This commit is contained in:
Shauren
2025-05-18 15:00:05 +02:00
committed by Ovahlord
parent 7f48085d11
commit 5e2fb0d520

View File

@@ -23,8 +23,6 @@
#include "ObjectGuid.h"
#include "Optional.h"
#include "Util.h"
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <fmt/ostream.h>
#include <string>
#include <string_view>
@@ -50,21 +48,21 @@ namespace Trinity::Impl::ChatCommands
using type = typename T::value_type;
};
template <size_t N>
inline constexpr char GetChar(char const (&s)[N], size_t i)
template <std::size_t Size>
struct string_literal
{
static_assert(N <= 25, "The EXACT_SEQUENCE macro can only be used with up to 25 character long literals. Specify them char-by-char (null terminated) as parameters to ExactSequence<> instead.");
return i >= N ? '\0' : s[i];
}
constexpr string_literal(char const (&str)[Size])
{
std::ranges::copy_n(str, Size, value.begin());
}
#define CHATCOMMANDS_IMPL_SPLIT_LITERAL_EXTRACT_CHAR(z, i, strliteral) \
BOOST_PP_COMMA_IF(i) Trinity::Impl::ChatCommands::GetChar(strliteral, i)
constexpr operator std::string_view() const
{
return { value.data(), value.size() - 1 };
}
#define CHATCOMMANDS_IMPL_SPLIT_LITERAL_CONSTRAINED(maxlen, strliteral) \
BOOST_PP_REPEAT(maxlen, CHATCOMMANDS_IMPL_SPLIT_LITERAL_EXTRACT_CHAR, strliteral)
// this creates always 25 elements - "abc" -> 'a', 'b', 'c', '\0', '\0', ... up to 25
#define CHATCOMMANDS_IMPL_SPLIT_LITERAL(strliteral) CHATCOMMANDS_IMPL_SPLIT_LITERAL_CONSTRAINED(25, strliteral)
std::array<char, Size> value;
};
TC_GAME_API ChatCommandResult TryConsumExactSequencee(std::string_view sequence, ChatHandler const* handler, std::string_view args);
}
@@ -85,23 +83,18 @@ namespace Trinity::ChatCommands
|* *|
\****************************************************************************************/
template <char... chars>
template <Impl::ChatCommands::string_literal Sequence>
struct ExactSequence : Trinity::Impl::ChatCommands::ContainerTag
{
using value_type = void;
ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args) const
{
return Trinity::Impl::ChatCommands::TryConsumExactSequencee(_string, handler, args);
return Trinity::Impl::ChatCommands::TryConsumExactSequencee(Sequence, handler, args);
}
private:
static constexpr std::array<char, sizeof...(chars)> _storage = { chars... };
static_assert(!_storage.empty() && (_storage.back() == '\0'), "ExactSequence parameters must be null terminated! Use the EXACT_SEQUENCE macro to make this easier!");
static constexpr std::string_view _string = { _storage.data(), std::string_view::traits_type::length(_storage.data()) };
};
#define EXACT_SEQUENCE(str) Trinity::ChatCommands::ExactSequence<CHATCOMMANDS_IMPL_SPLIT_LITERAL(str)>
#define EXACT_SEQUENCE(str) Trinity::ChatCommands::ExactSequence<str>
struct Tail : std::string_view, Trinity::Impl::ChatCommands::ContainerTag
{