From feaaa595cae735bb6093b24a88562c27b2723cfe Mon Sep 17 00:00:00 2001 From: Treeston Date: Thu, 10 Sep 2020 15:19:17 +0200 Subject: Core/ChatCommands: make ExactSequence more readable --- .../game/Chat/ChatCommands/ChatCommandTags.h | 43 ++++++++++++++-------- 1 file changed, 28 insertions(+), 15 deletions(-) (limited to 'src/server/game/Chat') diff --git a/src/server/game/Chat/ChatCommands/ChatCommandTags.h b/src/server/game/Chat/ChatCommands/ChatCommandTags.h index 011782a41cc..3fa8555ddec 100644 --- a/src/server/game/Chat/ChatCommands/ChatCommandTags.h +++ b/src/server/game/Chat/ChatCommands/ChatCommandTags.h @@ -24,6 +24,8 @@ #include "ObjectGuid.h" #include "Optional.h" #include "Util.h" +#include +#include #include #include #include @@ -45,6 +47,22 @@ namespace Trinity::Impl::ChatCommands { using type = typename T::value_type; }; + + template + inline constexpr char GetChar(char const (&s)[N], size_t i) + { + 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]; + } + +#define CHATCOMMANDS_IMPL_SPLIT_LITERAL_EXTRACT_CHAR(z, i, strliteral) \ + BOOST_PP_COMMA_IF(i) Trinity::Impl::ChatCommands::GetChar(strliteral, i) + +#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) } namespace Trinity::ChatCommands @@ -60,35 +78,30 @@ namespace Trinity::ChatCommands |* *| \****************************************************************************************/ - template + template struct ExactSequence : Trinity::Impl::ChatCommands::ContainerTag { using value_type = void; - static constexpr size_t N = (sizeof...(chars) + 1); - - static bool Match(char const* pos) - { - if (std::toupper(*(pos++)) != std::toupper(c1)) - return false; - else if constexpr (sizeof...(chars) > 0) - return ExactSequence::Match(pos); - else - return true; - } - Optional TryConsume(std::string_view args) const { - if ((N <= args.length()) && ExactSequence::Match(args.data())) + if (StringStartsWithI(args, _string)) { - auto [remainingToken, tail] = Trinity::Impl::ChatCommands::tokenize(args.substr(N)); + auto [remainingToken, tail] = Trinity::Impl::ChatCommands::tokenize(args.substr(_string.length())); if (remainingToken.empty()) // if this is not empty, then we did not consume the full token return tail; } return std::nullopt; } + + private: + static constexpr std::array _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() }; }; +#define EXACT_SEQUENCE(str) Trinity::ChatCommands::ExactSequence + struct Tail : std::string_view, Trinity::Impl::ChatCommands::ContainerTag { using value_type = std::string_view; -- cgit v1.2.3