diff options
| author | Treeston <treeston.mmoc@gmail.com> | 2020-08-17 01:05:09 +0200 |
|---|---|---|
| committer | Treeston <treeston.mmoc@gmail.com> | 2020-08-17 01:05:09 +0200 |
| commit | 7bceff1b2aa463f8e28277cc8c6eb2eda1952bb4 (patch) | |
| tree | a61f3f958ac6703641c84b9cdacd2e6ec1852077 /src/server/game/Chat/ChatCommands | |
| parent | 1aeb7a09804c81adf759cc8fe7a1b8664a19b7a7 (diff) | |
revert 1aeb7a0 and f9e7dbd until I can work around GCC being silly
Diffstat (limited to 'src/server/game/Chat/ChatCommands')
4 files changed, 173 insertions, 174 deletions
diff --git a/src/server/game/Chat/ChatCommands/ChatCommandArgs.cpp b/src/server/game/Chat/ChatCommands/ChatCommandArgs.cpp index fb94f6811b3..62ed5afc6c2 100644 --- a/src/server/game/Chat/ChatCommands/ChatCommandArgs.cpp +++ b/src/server/game/Chat/ChatCommands/ChatCommandArgs.cpp @@ -31,9 +31,9 @@ struct AchievementVisitor }; char const* Trinity::ChatCommands::ArgInfo<AchievementEntry const*>::TryConsume(AchievementEntry const*& data, char const* args) { - Variant<Hyperlink<achievement>, uint32> val; + Variant <Hyperlink<achievement>, uint32> val; if ((args = CommandArgsConsumerSingle<decltype(val)>::TryConsumeTo(val, args))) - data = val.visit(AchievementVisitor()); + data = boost::apply_visitor(AchievementVisitor(), val); return args; } @@ -47,7 +47,7 @@ char const* Trinity::ChatCommands::ArgInfo<GameTele const*>::TryConsume(GameTele { Variant<Hyperlink<tele>, std::string> val; if ((args = CommandArgsConsumerSingle<decltype(val)>::TryConsumeTo(val, args))) - data = val.visit(GameTeleVisitor()); + data = boost::apply_visitor(GameTeleVisitor(), val); return args; } @@ -61,22 +61,21 @@ char const* Trinity::ChatCommands::ArgInfo<SpellInfo const*>::TryConsume(SpellIn { Variant<Hyperlink<spell>, uint32> val; if ((args = CommandArgsConsumerSingle<decltype(val)>::TryConsumeTo(val, args))) - data = val.visit(SpellInfoVisitor()); + data = boost::apply_visitor(SpellInfoVisitor(), val); return args; } +struct BoolVisitor +{ + using value_type = bool; + value_type operator()(uint32 i) const { return !!i; } + value_type operator()(ExactSequence<'o', 'n'>) const { return true; } + value_type operator()(ExactSequence<'o', 'f', 'f'>) const { return false; } +}; char const* Trinity::ChatCommands::ArgInfo<bool>::TryConsume(bool& data, char const* args) { - std::string val; - if ((args = CommandArgsConsumerSingle<std::string>::TryConsumeTo(val, args))) - { - strToLower(val); - if (val == "on" || val == "yes" || val == "true" || val == "1" || val == "y") - data = true; - else if (val == "off" || val == "no" || val == "false" || val == "0" || val == "n") - data = false; - else - return nullptr; - } + Variant<uint32, ExactSequence<'o', 'n'>, ExactSequence<'o', 'f', 'f'>> val; + if ((args = CommandArgsConsumerSingle<decltype(val)>::TryConsumeTo(val, args))) + data = boost::apply_visitor(BoolVisitor(), val); return args; } diff --git a/src/server/game/Chat/ChatCommands/ChatCommandArgs.h b/src/server/game/Chat/ChatCommands/ChatCommandArgs.h index d7fa5cf65db..c9e0723fbf8 100644 --- a/src/server/game/Chat/ChatCommands/ChatCommandArgs.h +++ b/src/server/game/Chat/ChatCommands/ChatCommandArgs.h @@ -50,7 +50,7 @@ struct ArgInfo<T, std::enable_if_t<std::is_integral_v<T> && std::is_signed_v<T>> static char const* TryConsume(T& val, char const* args) { char const* next = args; - std::string token(args, Trinity::Impl::ChatCommands::tokenize(next)); + std::string token(args, tokenize(next)); try { size_t processedChars = 0; @@ -70,7 +70,7 @@ struct ArgInfo<T, std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T static char const* TryConsume(T& val, char const* args) { char const* next = args; - std::string token(args, Trinity::Impl::ChatCommands::tokenize(next)); + std::string token(args, tokenize(next)); try { size_t processedChars = 0; @@ -90,7 +90,7 @@ struct ArgInfo<T, std::enable_if_t<std::is_floating_point_v<T>>> static char const* TryConsume(T& val, char const* args) { char const* next = args; - std::string token(args, Trinity::Impl::ChatCommands::tokenize(next)); + std::string token(args, tokenize(next)); try { size_t processedChars = 0; @@ -110,7 +110,7 @@ struct ArgInfo<std::string, void> static char const* TryConsume(std::string& val, char const* args) { char const* next = args; - if (size_t len = Trinity::Impl::ChatCommands::tokenize(next)) + if (size_t len = tokenize(next)) { val.assign(args, len); return next; diff --git a/src/server/game/Chat/ChatCommands/ChatCommandHelpers.h b/src/server/game/Chat/ChatCommands/ChatCommandHelpers.h index e22823e5d35..ff9b5a3b8fc 100644 --- a/src/server/game/Chat/ChatCommands/ChatCommandHelpers.h +++ b/src/server/game/Chat/ChatCommands/ChatCommandHelpers.h @@ -20,50 +20,58 @@ #include <type_traits> -namespace Trinity::ChatCommands +namespace Trinity +{ +namespace ChatCommands { - static constexpr char COMMAND_DELIMITER = ' '; - template <typename T, typename = void> - struct tag_base - { - using type = T; - }; +static constexpr char COMMAND_DELIMITER = ' '; - template <typename T> - using tag_base_t = typename tag_base<T>::type; +/***************** HELPERS *************************\ +|* These really aren't for outside use... *| +\***************************************************/ +inline std::size_t tokenize(char const*& end) +{ + std::size_t len = 0; + for (; *end && *end != COMMAND_DELIMITER; ++end, ++len); + for (; *end && *end == COMMAND_DELIMITER; ++end); + return len; } -namespace Trinity::Impl::ChatCommands +template <typename T, typename = void> +struct tag_base { - /***************** HELPERS *************************\ - |* These really aren't for outside use... *| - \***************************************************/ - inline std::size_t tokenize(char const*& end) - { - std::size_t len = 0; - for (; *end && *end != Trinity::ChatCommands::COMMAND_DELIMITER; ++end, ++len); - for (; *end && *end == Trinity::ChatCommands::COMMAND_DELIMITER; ++end); - return len; - } + using type = T; +}; - template <typename T, typename... Ts> - struct are_all_assignable - { - static constexpr bool value = (std::is_assignable_v<T&, Ts> && ...); - }; +template <typename T> +using tag_base_t = typename tag_base<T>::type; - template <std::size_t index, typename T1, typename... Ts> - struct get_nth : get_nth<index-1, Ts...> { }; +template <typename...> +struct are_all_assignable +{ + static constexpr bool value = true; +}; + +template <typename T1, typename T2, typename... Ts> +struct are_all_assignable<T1, T2, Ts...> +{ + static constexpr bool value = std::is_assignable_v<T1&, T2> && are_all_assignable<T1, Ts...>::value; +}; - template <typename T1, typename... Ts> - struct get_nth<0, T1, Ts...> - { - using type = T1; - }; +template <std::size_t index, typename T1, typename... Ts> +struct get_nth : get_nth<index-1, Ts...> { }; - template <std::size_t index, typename... Ts> - using get_nth_t = typename get_nth<index, Ts...>::type; +template <typename T1, typename... Ts> +struct get_nth<0, T1, Ts...> +{ + using type = T1; +}; + +template <std::size_t index, typename... Ts> +using get_nth_t = typename get_nth<index, Ts...>::type; + +} } #endif diff --git a/src/server/game/Chat/ChatCommands/ChatCommandTags.h b/src/server/game/Chat/ChatCommands/ChatCommandTags.h index 3451b98a098..feffc25aa25 100644 --- a/src/server/game/Chat/ChatCommands/ChatCommandTags.h +++ b/src/server/game/Chat/ChatCommands/ChatCommandTags.h @@ -22,158 +22,150 @@ #include "ChatCommandHelpers.h" #include "Hyperlinks.h" #include "Optional.h" +#include <boost/variant.hpp> #include <cmath> #include <cstring> -#include <iostream> #include <string> #include <tuple> #include <type_traits> #include <utility> -#include <variant> -namespace Trinity::ChatCommands +namespace Trinity { - /************************** CONTAINER TAGS **********************************************\ - |* Simple holder classes to differentiate between extraction methods *| - |* Should inherit from ContainerTag for template identification *| - |* Must implement the following: *| - |* - TryConsume: char const* -> char const* *| - |* returns nullptr if no match, otherwise pointer to first character of next token *| - |* - typedef value_type of type that is contained within the tag *| - |* - cast operator to value_type *| - |* *| - \****************************************************************************************/ - struct ContainerTag {}; - template <typename T> - struct tag_base<T, std::enable_if_t<std::is_base_of_v<ContainerTag, T>>> +namespace ChatCommands +{ +/************************** CONTAINER TAGS **********************************************\ +|* Simple holder classes to differentiate between extraction methods *| +|* Should inherit from ContainerTag for template identification *| +|* Must implement the following: *| +|* - TryConsume: char const* -> char const* *| +|* returns nullptr if no match, otherwise pointer to first character of next token *| +|* - typedef value_type of type that is contained within the tag *| +|* - cast operator to value_type *| +|* *| +\****************************************************************************************/ +struct ContainerTag {}; +template <typename T> +struct tag_base<T, std::enable_if_t<std::is_base_of_v<ContainerTag, T>>> +{ + using type = typename T::value_type; +}; + +template <char c1, char... chars> +struct ExactSequence : public ContainerTag +{ + using value_type = void; + + static constexpr bool isSingleChar = !sizeof...(chars); + + template <bool C = isSingleChar> + static typename std::enable_if_t<!C, char const*> _TryConsume(char const* pos) { - using type = typename T::value_type; - }; + if (*(pos++) == c1) + return ExactSequence<chars...>::_TryConsume(pos); + else + return nullptr; + } - template <char c1, char... chars> - struct ExactSequence : public ContainerTag + template <bool C = isSingleChar> + static typename std::enable_if_t<C, char const*> _TryConsume(char const* pos) { - using value_type = void; + if (*(pos++) != c1) + return nullptr; + // if more of string is left, tokenize should return 0 (otherwise we didn't reach end of token yet) + return *pos && tokenize(pos) ? nullptr : pos; + } - static char const* _TryConsume(char const* pos) + char const* TryConsume(char const* pos) const { return ExactSequence::_TryConsume(pos); } +}; + +template <typename linktag> +struct Hyperlink : public ContainerTag +{ + typedef typename linktag::value_type value_type; + typedef advstd::remove_cvref_t<value_type> storage_type; + + public: + operator value_type() const { return val; } + value_type operator*() const { return val; } + storage_type const* operator->() const { return &val; } + + char const* TryConsume(char const* pos) { - if (*(pos++) == c1) - { - if constexpr (sizeof...(chars)) - return ExactSequence<chars...>::_TryConsume(pos); - else if (Trinity::Impl::ChatCommands::tokenize(pos)) /* we did not consume the entire token */ - return nullptr; - else - return pos; - } - else + Trinity::Hyperlinks::HyperlinkInfo info = Trinity::Hyperlinks::ParseHyperlink(pos); + // invalid hyperlinks cannot be consumed + if (!info) + return nullptr; + + // check if we got the right tag + if (info.tag.second != strlen(linktag::tag())) + return nullptr; + if (strncmp(info.tag.first, linktag::tag(), strlen(linktag::tag())) != 0) return nullptr; + + // store value + if (!linktag::StoreTo(val, info.data.first, info.data.second)) + return nullptr; + + // finally, skip to end of token + pos = info.next; + tokenize(pos); + + // return final pos + return pos; } - char const* TryConsume(char const* pos) const { return ExactSequence::_TryConsume(pos); } - }; + private: + storage_type val; +}; - template <typename linktag> - struct Hyperlink : public ContainerTag - { - using value_type = typename linktag::value_type; - using storage_type = advstd::remove_cvref_t<value_type>; - - public: - operator value_type() const { return val; } - value_type operator*() const { return val; } - storage_type const* operator->() const { return &val; } - - char const* TryConsume(char const* pos) - { - Trinity::Hyperlinks::HyperlinkInfo info = Trinity::Hyperlinks::ParseHyperlink(pos); - // invalid hyperlinks cannot be consumed - if (!info) - return nullptr; - - // check if we got the right tag - if (info.tag.second != strlen(linktag::tag())) - return nullptr; - if (strncmp(info.tag.first, linktag::tag(), strlen(linktag::tag())) != 0) - return nullptr; - - // store value - if (!linktag::StoreTo(val, info.data.first, info.data.second)) - return nullptr; - - // finally, skip to end of token - pos = info.next; - Trinity::Impl::ChatCommands::tokenize(pos); - - // return final pos - return pos; - } - - private: - storage_type val; - }; - - // pull in link tags for user convenience - using namespace ::Trinity::Hyperlinks::LinkTags; -} +// pull in link tags for user convenience +using namespace ::Trinity::Hyperlinks::LinkTags; /************************** VARIANT TAG LOGIC *********************************\ |* This has some special handling over in ChatCommand.h *| \******************************************************************************/ -namespace Trinity::Impl -{ - template <typename T> - struct CastToVisitor { - template <typename U> - T operator()(U const& v) const { return v; } - }; -} +template <typename T> +struct CastToVisitor { + using result_type = T; + + template <typename U> + T operator()(U const& v) const { return v; } +}; -namespace Trinity::ChatCommands +template <typename T1, typename... Ts> +struct Variant : public boost::variant<T1, Ts...> { - template <typename T1, typename... Ts> - struct Variant : public std::variant<T1, Ts...> - { - using first_type = tag_base_t<T1>; - static constexpr bool have_operators = Trinity::Impl::ChatCommands::are_all_assignable<first_type, tag_base_t<Ts>...>::value; + using first_type = tag_base_t<T1>; + static constexpr bool have_operators = are_all_assignable<first_type, tag_base_t<Ts>...>::value; - template <bool C = have_operators> - std::enable_if_t<C, first_type> operator*() const - { - return visit(Trinity::Impl::CastToVisitor<first_type>()); - } + template <bool C = have_operators> + operator std::enable_if_t<C, first_type>() + { + return operator*(); + } - template <bool C = have_operators> - operator std::enable_if_t<C, first_type>() const - { - return operator*(); - } + template <bool C = have_operators> + std::enable_if_t<C, first_type> operator*() + { + return boost::apply_visitor(CastToVisitor<first_type>(), *this); + } - template <typename T> - Variant& operator=(T&& arg) { std::variant<T1, Ts...>::operator=(std::forward<T>(arg)); return *this; } + template <bool C = have_operators> + std::enable_if_t<C, first_type const&> operator*() const + { + return boost::apply_visitor(CastToVisitor<first_type const&>(), *this); + } - template <size_t index> - constexpr decltype(auto) get() { return std::get<index>(*this); } - template <size_t index> - constexpr decltype(auto) get() const { return std::get<index>(*this); } + template <typename T> + Variant& operator=(T&& arg) { boost::variant<T1, Ts...>::operator=(std::forward<T>(arg)); return *this; } - template <typename T> - constexpr decltype(auto) visit(T&& arg) const { return std::visit(std::forward<T>(arg), *this); } + template <size_t index> + decltype(auto) get() const { return boost::get<get_nth_t<index, T1, Ts...>>(*this); } +}; - template <typename T> - constexpr bool holds_alternative() const { return std::holds_alternative<T>(*this); } - }; } - -/* make the correct operator<< to use explicit, because otherwise the compiler gets confused with the implicit std::variant conversion */ -namespace std -{ - template <typename... Ts> - auto operator<<(std::ostream& os, Trinity::ChatCommands::Variant<Ts...> const& v) -> std::enable_if_t<Trinity::ChatCommands::Variant<Ts...>::have_operators, std::ostream&> - { - return (os << *v); - } } #endif |
