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)
 
std::string_view Acore::ChatCommands::format_as (QuotedString const &qs)
 

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
145 inline std::string_view format_as(QuotedString const& qs)
146 {
147 return std::string_view(qs);
148 }
149
151 {
152 using value_type = uint32;
153
154 operator uint32() const { return _id; }
155 operator std::string const& () const { return _name; }
156 operator std::string_view() const { return { _name }; }
157
158 uint32 GetID() const { return _id; }
159 std::string const& GetName() const { return _name; }
160
161 ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args);
162
163 private:
164 uint32 _id;
165 std::string _name;
166 };
167
169 {
170 using value_type = Player*;
171
172 PlayerIdentifier() : _name(), _guid(), _player(nullptr) {}
173 PlayerIdentifier(Player& player);
174
175 operator ObjectGuid() const { return _guid; }
176 operator std::string const&() const { return _name; }
177 operator std::string_view() const { return _name; }
178
179 std::string const& GetName() const { return _name; }
180 ObjectGuid GetGUID() const { return _guid; }
181 bool IsConnected() const { return (_player != nullptr); }
182 Player* GetConnectedPlayer() const { return _player; }
183
184 ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args);
185
186 static Optional<PlayerIdentifier> FromTarget(ChatHandler* handler);
187 static Optional<PlayerIdentifier> FromSelf(ChatHandler* handler);
188 static Optional<PlayerIdentifier> FromTargetOrSelf(ChatHandler* handler)
189 {
190 if (Optional<PlayerIdentifier> fromTarget = FromTarget(handler))
191 return fromTarget;
192 else
193 return FromSelf(handler);
194 }
195
196 private:
197 std::string _name;
198 ObjectGuid _guid;
199 Player* _player;
200 };
201
202 template <typename linktag>
204 {
205 using value_type = typename linktag::value_type;
206 using storage_type = std::remove_cvref_t<value_type>;
207
208 operator value_type() const { return val; }
209 value_type operator*() const { return val; }
210 storage_type const* operator->() const { return &val; }
211
212 ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args)
213 {
215 // invalid hyperlinks cannot be consumed
216 if (!info)
217 return std::nullopt;
218
219 // check if we got the right tag
220 if (info.tag != linktag::tag())
221 return std::nullopt;
222
223 // store value
224 if (!linktag::StoreTo(val, info.data))
226
227 // finally, skip any potential delimiters
228 auto [token, next] = Acore::Impl::ChatCommands::tokenize(info.tail);
229 if (token.empty()) /* empty token = first character is delimiter, skip past it */
230 return next;
231 else
232 return info.tail;
233 }
234
235 private:
236 storage_type val;
237 };
238
239 // pull in link tags for user convenience
240 using namespace ::Acore::Hyperlinks::LinkTags;
241}
242
243namespace Acore::Impl
244{
245 template <typename T>
246 struct CastToVisitor
247 {
248 template <typename U>
249 T operator()(U const& v) const { return v; }
250 };
251}
252
253namespace Acore::ChatCommands
254{
255 template <typename T1, typename... Ts>
256 struct Variant : public std::variant<T1, Ts...>
257 {
258 using base = std::variant<T1, Ts...>;
259
262
263 template <bool C = have_operators>
264 std::enable_if_t<C, first_type> operator*() const
265 {
267 }
268
269 template <bool C = have_operators>
270 operator std::enable_if_t<C, first_type>() const
271 {
272 return operator*();
273 }
274
275 template<bool C = have_operators>
276 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
277 {
278 return operator*();
279 }
280
281 template <bool C = have_operators>
282 std::enable_if_t<C, bool> operator!() const { return !**this; }
283
284 template <typename T>
285 Variant& operator=(T&& arg) { base::operator=(std::forward<T>(arg)); return *this; }
286
287 template <std::size_t index>
288 constexpr decltype(auto) get() { return std::get<index>(static_cast<base&>(*this)); }
289 template <std::size_t index>
290 constexpr decltype(auto) get() const { return std::get<index>(static_cast<base const&>(*this)); }
291 template <typename type>
292 constexpr decltype(auto) get() { return std::get<type>(static_cast<base&>(*this)); }
293 template <typename type>
294 constexpr decltype(auto) get() const { return std::get<type>(static_cast<base const&>(*this)); }
295
296 template <typename T>
297 constexpr decltype(auto) visit(T&& arg) { return std::visit(std::forward<T>(arg), static_cast<base&>(*this)); }
298 template <typename T>
299 constexpr decltype(auto) visit(T&& arg) const { return std::visit(std::forward<T>(arg), static_cast<base const&>(*this)); }
300
301 template <typename T>
302 constexpr bool holds_alternative() const { return std::holds_alternative<T>(static_cast<base const&>(*this)); }
303
304 template <bool C = have_operators>
305 friend std::enable_if_t<C, std::ostream&> operator<<(std::ostream& os, Acore::ChatCommands::Variant<T1, Ts...> const& v)
306 {
307 return (os << *v);
308 }
309 };
310}
311
312#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:1021
@ LANG_CMDPARSER_LINKDATA_INVALID
Definition Language.h:1010
@ LANG_CMDPARSER_INVALID_UTF8
Definition Language.h:1009
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:24
auto format_as(T f)
Definition StringFormat.h:123
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:1084
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:258
Variant & operator=(T &&arg)
Definition ChatCommandTags.h:286
constexpr decltype(auto) visit(T &&arg)
Definition ChatCommandTags.h:298
Acore::Impl::ChatCommands::tag_base_t< T1 > first_type
Definition ChatCommandTags.h:261
std::enable_if_t< C, bool > operator!() const
Definition ChatCommandTags.h:283
static constexpr bool have_operators
Definition ChatCommandTags.h:262
friend std::enable_if_t< C, std::ostream & > operator<<(std::ostream &os, Acore::ChatCommands::Variant< T1, Ts... > const &v)
Definition ChatCommandTags.h:306
std::variant< T1, Ts... > base
Definition ChatCommandTags.h:259
constexpr bool holds_alternative() const
Definition ChatCommandTags.h:303
std::enable_if_t< C, first_type > operator*() const
Definition ChatCommandTags.h:265
Definition ChatCommandTags.h:248
T operator()(U const &v) const
Definition ChatCommandTags.h:250
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)>