Core/ChatCommands: Add support for enum type arguments (PR #25242)

This commit is contained in:
Peter Keresztes Schmidt
2020-08-16 14:11:21 +02:00
committed by GitHub
parent 6c7837f947
commit 5e40eb20e2
4 changed files with 102 additions and 6 deletions

View File

@@ -469,6 +469,11 @@ void wstrToUpper(std::wstring& str)
std::transform(str.begin(), str.end(), str.begin(), wcharToUpper);
}
void strToLower(std::string& str)
{
std::transform(str.begin(), str.end(), str.begin(), [](char c) { return std::tolower(c); });
}
void wstrToLower(std::wstring& str)
{
std::transform(str.begin(), str.end(), str.begin(), wcharToLower);
@@ -665,6 +670,20 @@ bool StringToBool(std::string const& str)
return lowerStr == "1" || lowerStr == "true" || lowerStr == "yes";
}
bool StringEqualI(std::string const& str1, std::string const& str2)
{
return std::equal(str1.begin(), str1.end(), str2.begin(), str2.end(),
[](char a, char b)
{
return std::tolower(a) == std::tolower(b);
});
}
bool StringStartsWith(std::string const& haystack, std::string const& needle)
{
return (haystack.rfind(needle, 0) == 0);
}
bool StringContainsStringI(std::string const& haystack, std::string const& needle)
{
return haystack.end() !=

View File

@@ -289,6 +289,7 @@ inline wchar_t wcharToLower(wchar_t wchar)
}
TC_COMMON_API void wstrToUpper(std::wstring& str);
TC_COMMON_API void strToLower(std::string& str);
TC_COMMON_API void wstrToLower(std::wstring& str);
TC_COMMON_API std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension);
@@ -341,6 +342,8 @@ inline std::vector<uint8> HexStrToByteVector(std::string const& str, bool revers
TC_COMMON_API bool StringToBool(std::string const& str);
TC_COMMON_API bool StringEqualI(std::string const& str1, std::string const& str2);
TC_COMMON_API bool StringStartsWith(std::string const& haystack, std::string const& needle);
TC_COMMON_API bool StringContainsStringI(std::string const& haystack, std::string const& needle);
template <typename T>
inline bool ValueContainsStringI(std::pair<T, std::string> const& haystack, std::string const& needle)

View File

@@ -20,6 +20,9 @@
#include "ChatCommandHelpers.h"
#include "ChatCommandTags.h"
#include "SmartEnum.h"
#include "Util.h"
#include <map>
struct GameTele;
@@ -99,6 +102,82 @@ struct ArgInfo<std::string, void>
}
};
// enum
template <typename T>
struct ArgInfo<T, std::enable_if_t<std::is_enum_v<T>>>
{
static std::map<std::string, Optional<T>> MakeSearchMap()
{
std::map<std::string, Optional<T>> map;
for (T val : EnumUtils::Iterate<T>())
{
EnumText text = EnumUtils::ToString(val);
std::string title(text.Title);
strToLower(title);
std::string constant(text.Constant);
strToLower(constant);
auto [constantIt, constantNew] = map.try_emplace(constant, val);
if (!constantNew)
constantIt->second = std::nullopt;
if (title != constant)
{
auto [titleIt, titleNew] = map.try_emplace(title, val);
if (!titleNew)
titleIt->second = std::nullopt;
}
}
return map;
}
static inline std::map<std::string, Optional<T>> const SearchMap = MakeSearchMap();
static T const* Match(std::string s)
{
strToLower(s);
auto it = SearchMap.lower_bound(s);
if (it == SearchMap.end() || !StringStartsWith(it->first, s)) // not a match
return nullptr;
auto it2 = it;
++it2;
if (it2 != SearchMap.end() && StringStartsWith(it2->first, s)) // not unique
return nullptr;
if (it->second)
return &*it->second;
else
return nullptr;
}
static char const* TryConsume(T& val, char const* args)
{
std::string strVal;
char const* ret = ArgInfo<std::string>::TryConsume(strVal, args);
if (!ret)
return nullptr;
if (T const* tmpVal = Match(strVal))
{
val = *tmpVal;
return ret;
}
// Value not found. Try to parse arg as underlying type and cast it to enum type
using U = std::underlying_type_t<T>;
U uVal = 0;
ret = ArgInfo<U>::TryConsume(uVal, args);
if (ret)
val = static_cast<T>(uVal);
return ret;
}
};
// a container tag
template <typename T>
struct ArgInfo<T, std::enable_if_t<std::is_base_of_v<ContainerTag, T>>>

View File

@@ -533,13 +533,8 @@ public:
}
//set npcflag of creature
static bool HandleNpcSetFlagCommand(ChatHandler* handler, char const* args)
static bool HandleNpcSetFlagCommand(ChatHandler* handler, NPCFlags npcFlags)
{
if (!*args)
return false;
uint32 npcFlags = (uint32) atoi(args);
Creature* creature = handler->getSelectedCreature();
if (!creature)