AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
ChatCommandTags.h File Reference
#include "ChatCommandHelpers.h"
#include "Hyperlinks.h"
#include "ObjectGuid.h"
#include "Optional.h"
#include "Util.h"
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <iostream>
#include <string>
#include <string_view>
#include <tuple>
#include <variant>

Go to the source code of this file.

Classes

struct  Acore::Impl::ChatCommands::ContainerTag
 
struct  Acore::Impl::ChatCommands::tag_base< T, std::enable_if_t< std::is_base_of_v< ContainerTag, T > > >
 
struct  Acore::ChatCommands::ExactSequence< chars >
 
struct  Acore::ChatCommands::Tail
 
struct  Acore::ChatCommands::WTail
 
struct  Acore::ChatCommands::QuotedString
 
struct  Acore::ChatCommands::AccountIdentifier
 
struct  Acore::ChatCommands::PlayerIdentifier
 
struct  Acore::ChatCommands::Hyperlink< linktag >
 
struct  Acore::Impl::CastToVisitor< T >
 
struct  Acore::ChatCommands::Variant< T1, Ts >
 

Namespaces

namespace  Acore
 
namespace  Acore::Impl
 
namespace  Acore::Impl::ChatCommands
 
namespace  Acore::ChatCommands
 

Macros

#define CHATCOMMANDS_IMPL_SPLIT_LITERAL_EXTRACT_CHAR(z, i, strliteral)    BOOST_PP_COMMA_IF(i) Acore::Impl::ChatCommands::GetChar(strliteral, i)
 
#define CHATCOMMANDS_IMPL_SPLIT_LITERAL_CONSTRAINED(maxlen, strliteral)    BOOST_PP_REPEAT(maxlen, CHATCOMMANDS_IMPL_SPLIT_LITERAL_EXTRACT_CHAR, strliteral)
 
#define CHATCOMMANDS_IMPL_SPLIT_LITERAL(strliteral)   CHATCOMMANDS_IMPL_SPLIT_LITERAL_CONSTRAINED(25, strliteral)
 
#define EXACT_SEQUENCE(str)   Acore::ChatCommands::ExactSequence<CHATCOMMANDS_IMPL_SPLIT_LITERAL(str)>
 

Functions

template<std::size_t N>
constexpr char Acore::Impl::ChatCommands::GetChar (char const (&s)[N], std::size_t i)
 

Macro Definition Documentation

◆ CHATCOMMANDS_IMPL_SPLIT_LITERAL

#define CHATCOMMANDS_IMPL_SPLIT_LITERAL (   strliteral)    CHATCOMMANDS_IMPL_SPLIT_LITERAL_CONSTRAINED(25, strliteral)

◆ CHATCOMMANDS_IMPL_SPLIT_LITERAL_CONSTRAINED

#define CHATCOMMANDS_IMPL_SPLIT_LITERAL_CONSTRAINED (   maxlen,
  strliteral 
)     BOOST_PP_REPEAT(maxlen, CHATCOMMANDS_IMPL_SPLIT_LITERAL_EXTRACT_CHAR, strliteral)
67{
68 /************************** CONTAINER TAGS **********************************************\
69 |* Simple holder classes to differentiate between extraction methods *|
70 |* Must inherit from Acore::Impl::ChatCommands::ContainerTag *|
71 |* Must implement the following: *|
72 |* - TryConsume: ChatHandler const*, std::string_view -> ChatCommandResult *|
73 |* - on match, returns tail of the provided argument string (as std::string_view) *|
74 |* - on specific error, returns error message (as std::string&& or char const*) *|
75 |* - on generic error, returns std::nullopt (this will print command usage) *|
76 |* *|
77 |* - typedef value_type of type that is contained within the tag *|
78 |* - cast operator to value_type *|
79 |* *|
80 \****************************************************************************************/
81
82 template <char... chars>
83 struct ExactSequence : Acore::Impl::ChatCommands::ContainerTag
84 {
85 using value_type = void;
86
87 ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args) const
88 {
89 if (args.empty())
90 return std::nullopt;
91 std::string_view start = args.substr(0, _string.length());
92 if (StringEqualI(start, _string))
93 {
94 auto [remainingToken, tail] = Acore::Impl::ChatCommands::tokenize(args.substr(_string.length()));
95 if (remainingToken.empty()) // if this is not empty, then we did not consume the full token
96 return tail;
97 start = args.substr(0, _string.length() + remainingToken.length());
98 }
100 }
101
102 private:
103 static constexpr std::array<char, sizeof...(chars)> _storage = { chars... };
104 static_assert(!_storage.empty() && (_storage.back() == '\0'), "ExactSequence parameters must be null terminated! Use the EXACT_SEQUENCE macro to make this easier!");
105 static constexpr std::string_view _string = { _storage.data(), std::string_view::traits_type::length(_storage.data()) };
106 };
107
108#define EXACT_SEQUENCE(str) Acore::ChatCommands::ExactSequence<CHATCOMMANDS_IMPL_SPLIT_LITERAL(str)>
109
110 struct Tail : std::string_view, Acore::Impl::ChatCommands::ContainerTag
111 {
112 using value_type = std::string_view;
113
114 using std::string_view::operator=;
115
116 ChatCommandResult TryConsume(ChatHandler const*, std::string_view args)
117 {
118 std::string_view::operator=(args);
119 return std::string_view();
120 }
121 };
122
123 struct WTail : std::wstring, Acore::Impl::ChatCommands::ContainerTag
124 {
125 using value_type = std::wstring;
126
127 using std::wstring::operator=;
128
129 ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args)
130 {
131 if (Utf8toWStr(args, *this))
132 return std::string_view();
133 else
135 }
136 };
137
138 struct QuotedString : std::string, Acore::Impl::ChatCommands::ContainerTag
139 {
140 using value_type = std::string;
141
142 AC_GAME_API ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args);
143 };
144
146 {
147 using value_type = uint32;
148
149 operator uint32() const { return _id; }
150 operator std::string const& () const { return _name; }
151 operator std::string_view() const { return { _name }; }
152
153 uint32 GetID() const { return _id; }
154 std::string const& GetName() const { return _name; }
155
156 ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args);
157
158 private:
159 uint32 _id;
160 std::string _name;
161 };
162
164 {
165 using value_type = Player*;
166
167 PlayerIdentifier() : _name(), _guid(), _player(nullptr) {}
168 PlayerIdentifier(Player& player);
169
170 operator ObjectGuid() const { return _guid; }
171 operator std::string const&() const { return _name; }
172 operator std::string_view() const { return _name; }
173
174 std::string const& GetName() const { return _name; }
175 ObjectGuid GetGUID() const { return _guid; }
176 bool IsConnected() const { return (_player != nullptr); }
177 Player* GetConnectedPlayer() const { return _player; }
178
179 ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args);
180
181 static Optional<PlayerIdentifier> FromTarget(ChatHandler* handler);
182 static Optional<PlayerIdentifier> FromSelf(ChatHandler* handler);
183 static Optional<PlayerIdentifier> FromTargetOrSelf(ChatHandler* handler)
184 {
185 if (Optional<PlayerIdentifier> fromTarget = FromTarget(handler))
186 return fromTarget;
187 else
188 return FromSelf(handler);
189 }
190
191 private:
192 std::string _name;
193 ObjectGuid _guid;
194 Player* _player;
195 };
196
197 template <typename linktag>
199 {
200 using value_type = typename linktag::value_type;
201 using storage_type = std::remove_cvref_t<value_type>;
202
203 operator value_type() const { return val; }
204 value_type operator*() const { return val; }
205 storage_type const* operator->() const { return &val; }
206
207 ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args)
208 {
210 // invalid hyperlinks cannot be consumed
211 if (!info)
212 return std::nullopt;
213
214 // check if we got the right tag
215 if (info.tag != linktag::tag())
216 return std::nullopt;
217
218 // store value
219 if (!linktag::StoreTo(val, info.data))
221
222 // finally, skip any potential delimiters
223 auto [token, next] = Acore::Impl::ChatCommands::tokenize(info.tail);
224 if (token.empty()) /* empty token = first character is delimiter, skip past it */
225 return next;
226 else
227 return info.tail;
228 }
229
230 private:
231 storage_type val;
232 };
233
234 // pull in link tags for user convenience
235 using namespace ::Acore::Hyperlinks::LinkTags;
236}
237
238namespace Acore::Impl
239{
240 template <typename T>
241 struct CastToVisitor
242 {
243 template <typename U>
244 T operator()(U const& v) const { return v; }
245 };
246}
247
248namespace Acore::ChatCommands
249{
250 template <typename T1, typename... Ts>
251 struct Variant : public std::variant<T1, Ts...>
252 {
253 using base = std::variant<T1, Ts...>;
254
257
258 template <bool C = have_operators>
259 std::enable_if_t<C, first_type> operator*() const
260 {
262 }
263
264 template <bool C = have_operators>
265 operator std::enable_if_t<C, first_type>() const
266 {
267 return operator*();
268 }
269
270 template<bool C = have_operators>
271 operator std::enable_if_t<C && !std::is_same_v<first_type, std::size_t> && std::is_convertible_v<first_type, std::size_t>, std::size_t>() const
272 {
273 return operator*();
274 }
275
276 template <bool C = have_operators>
277 std::enable_if_t<C, bool> operator!() const { return !**this; }
278
279 template <typename T>
280 Variant& operator=(T&& arg) { base::operator=(std::forward<T>(arg)); return *this; }
281
282 template <std::size_t index>
283 constexpr decltype(auto) get() { return std::get<index>(static_cast<base&>(*this)); }
284 template <std::size_t index>
285 constexpr decltype(auto) get() const { return std::get<index>(static_cast<base const&>(*this)); }
286 template <typename type>
287 constexpr decltype(auto) get() { return std::get<type>(static_cast<base&>(*this)); }
288 template <typename type>
289 constexpr decltype(auto) get() const { return std::get<type>(static_cast<base const&>(*this)); }
290
291 template <typename T>
292 constexpr decltype(auto) visit(T&& arg) { return std::visit(std::forward<T>(arg), static_cast<base&>(*this)); }
293 template <typename T>
294 constexpr decltype(auto) visit(T&& arg) const { return std::visit(std::forward<T>(arg), static_cast<base const&>(*this)); }
295
296 template <typename T>
297 constexpr bool holds_alternative() const { return std::holds_alternative<T>(static_cast<base const&>(*this)); }
298
299 template <bool C = have_operators>
300 friend std::enable_if_t<C, std::ostream&> operator<<(std::ostream& os, Acore::ChatCommands::Variant<T1, Ts...> const& v)
301 {
302 return (os << *v);
303 }
304 };
305}
306
307#endif
#define AC_GAME_API
Definition Define.h:94
std::uint32_t uint32
Definition Define.h:107
@ LANG_CMDPARSER_EXACT_SEQ_MISMATCH
Definition Language.h:1007
@ LANG_CMDPARSER_LINKDATA_INVALID
Definition Language.h:996
@ LANG_CMDPARSER_INVALID_UTF8
Definition Language.h:995
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:24
bool Utf8toWStr(char const *utf8str, std::size_t csize, wchar_t *wstr, std::size_t &wsize)
Definition Util.cpp:281
bool StringEqualI(std::string_view a, std::string_view b)
Definition Util.cpp:592
Definition Chat.h:37
Definition ObjectGuid.h:118
Definition Player.h:1081
bool GetName(uint32 accountId, std::string &name)
Definition AccountMgr.cpp:257
Definition ChatCommand.h:38
AC_GAME_API std::string GetAcoreString(ChatHandler const *handler, AcoreStrings which)
Definition ChatCommandHelpers.cpp:27
std::string FormatAcoreString(ChatHandler const *handler, AcoreStrings which, Ts &&... args)
Definition ChatCommandHelpers.h:125
typename tag_base< T >::type tag_base_t
Definition ChatCommandHelpers.h:46
TokenizeResult tokenize(std::string_view args)
Definition ChatCommandHelpers.h:54
Definition CryptoGenerics.h:29
Definition ChatCommandTags.h:253
Variant & operator=(T &&arg)
Definition ChatCommandTags.h:281
constexpr decltype(auto) visit(T &&arg)
Definition ChatCommandTags.h:293
Acore::Impl::ChatCommands::tag_base_t< T1 > first_type
Definition ChatCommandTags.h:256
std::enable_if_t< C, bool > operator!() const
Definition ChatCommandTags.h:278
static constexpr bool have_operators
Definition ChatCommandTags.h:257
friend std::enable_if_t< C, std::ostream & > operator<<(std::ostream &os, Acore::ChatCommands::Variant< T1, Ts... > const &v)
Definition ChatCommandTags.h:301
std::variant< T1, Ts... > base
Definition ChatCommandTags.h:254
constexpr bool holds_alternative() const
Definition ChatCommandTags.h:298
std::enable_if_t< C, first_type > operator*() const
Definition ChatCommandTags.h:260
Definition ChatCommandTags.h:243
T operator()(U const &v) const
Definition ChatCommandTags.h:245
Definition ChatCommandHelpers.h:100
Definition ChatCommandTags.h:40
Definition ChatCommandHelpers.h:71

◆ CHATCOMMANDS_IMPL_SPLIT_LITERAL_EXTRACT_CHAR

#define CHATCOMMANDS_IMPL_SPLIT_LITERAL_EXTRACT_CHAR (   z,
  i,
  strliteral 
)     BOOST_PP_COMMA_IF(i) Acore::Impl::ChatCommands::GetChar(strliteral, i)

◆ EXACT_SEQUENCE

#define EXACT_SEQUENCE (   str)    Acore::ChatCommands::ExactSequence<CHATCOMMANDS_IMPL_SPLIT_LITERAL(str)>