TrinityCore
PacketUtilities.h
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef PacketUtilities_h__
19#define PacketUtilities_h__
20
21#include "ByteBuffer.h"
22#include "Duration.h"
23#include "Tuples.h"
24#include <short_alloc/short_alloc.h>
25#include <string_view>
26#include <ctime>
27
28namespace WorldPackets
29{
31 {
32 public:
33 InvalidStringValueException(std::string const& value);
34
35 std::string const& GetInvalidValue() const { return _value; }
36
37 private:
38 std::string _value;
39 };
40
42 {
43 public:
44 InvalidUtf8ValueException(std::string const& value);
45 };
46
48 {
49 public:
50 InvalidHyperlinkException(std::string const& value);
51 };
52
54 {
55 public:
56 IllegalHyperlinkException(std::string const& value);
57 };
58
59 namespace Strings
60 {
61 struct RawBytes { static bool Validate(std::string const& /*value*/) { return true; } };
62 template<std::size_t MaxBytesWithoutNullTerminator>
63 struct ByteSize { static bool Validate(std::string const& value) { return value.size() <= MaxBytesWithoutNullTerminator; } };
64 struct Utf8 { static bool Validate(std::string const& value); };
65 struct Hyperlinks { static bool Validate(std::string const& value); };
66 struct NoHyperlinks { static bool Validate(std::string const& value); };
67 }
68
72 template<std::size_t MaxBytesWithoutNullTerminator, typename... Validators>
73 class String
74 {
75 using ValidatorList = std::conditional_t<!Trinity::has_type<Strings::RawBytes, std::tuple<Validators...>>::value,
76 std::tuple<Strings::ByteSize<MaxBytesWithoutNullTerminator>, Strings::Utf8, Validators...>,
77 std::tuple<Strings::ByteSize<MaxBytesWithoutNullTerminator>, Validators...>>;
78
79 public:
80 bool empty() const { return _storage.empty(); }
81 std::size_t length() const { return _storage.length(); }
82 char const* c_str() const { return _storage.c_str(); }
83
84 operator std::string_view() const { return _storage; }
85 operator std::string&() { return _storage; }
86 operator std::string const&() const { return _storage; }
87
88 std::string&& Move() { return std::move(_storage); }
89
90 friend ByteBuffer& operator>>(ByteBuffer& data, String& value)
91 {
92 std::string string = data.ReadCString(false);
93 Validate(string);
94 value._storage = std::move(string);
95 return data;
96 }
97
98 String& operator=(std::string const& value)
99 {
100 Validate(value);
101 _storage = value;
102 return *this;
103 }
104
105 String& operator=(std::string&& value)
106 {
107 Validate(value);
108 _storage = std::move(value);
109 return *this;
110 }
111
112 private:
113 static bool Validate(std::string const& value)
114 {
115 return ValidateNth(value, std::make_index_sequence<std::tuple_size_v<ValidatorList>>{});
116 }
117
118 template<std::size_t... indexes>
119 static bool ValidateNth(std::string const& value, std::index_sequence<indexes...>)
120 {
121 return (std::tuple_element_t<indexes, ValidatorList>::Validate(value) && ...);
122 }
123
124 std::string _storage;
125 };
126
128 {
129 public:
130 PacketArrayMaxCapacityException(std::size_t requestedSize, std::size_t sizeLimit);
131 };
132
136 template<typename T, std::size_t N>
137 class Array
138 {
139 public:
140 using allocator_type = short_alloc::short_alloc<T, (N * sizeof(T) + (alignof(std::max_align_t) - 1)) & ~(alignof(std::max_align_t) - 1)>;
141 using arena_type = typename allocator_type::arena_type;
142
143 using storage_type = std::vector<T, allocator_type>;
144
145 using max_capacity = std::integral_constant<std::size_t, N>;
146
147 using value_type = typename storage_type::value_type;
148 using size_type = typename storage_type::size_type;
149 using pointer = typename storage_type::pointer;
150 using const_pointer = typename storage_type::const_pointer;
151 using reference = typename storage_type::reference;
152 using const_reference = typename storage_type::const_reference;
153 using iterator = typename storage_type::iterator;
154 using const_iterator = typename storage_type::const_iterator;
155
157
158 Array(Array const& other) : Array()
159 {
160 for (T const& element : other)
161 _storage.push_back(element);
162 }
163
164 Array(Array&& other) noexcept = delete;
165
166 Array& operator=(Array const& other)
167 {
168 if (this == &other)
169 return *this;
170
171 _storage.clear();
172 for (T const& element : other)
173 _storage.push_back(element);
174
175 return *this;
176 }
177
178 Array& operator=(Array&& other) noexcept = delete;
179
180 iterator begin() { return _storage.begin(); }
181 const_iterator begin() const { return _storage.begin(); }
182
183 iterator end() { return _storage.end(); }
184 const_iterator end() const { return _storage.end(); }
185
186 pointer data() { return _storage.data(); }
187 const_pointer data() const { return _storage.data(); }
188
189 size_type size() const { return _storage.size(); }
190 bool empty() const { return _storage.empty(); }
191
194
195 void resize(size_type newSize)
196 {
197 if (newSize > max_capacity::value)
198 throw PacketArrayMaxCapacityException(newSize, max_capacity::value);
199
200 _storage.resize(newSize);
201 }
202
203 void push_back(value_type const& value)
204 {
205 if (_storage.size() >= max_capacity::value)
206 throw PacketArrayMaxCapacityException(_storage.size() + 1, max_capacity::value);
207
208 _storage.push_back(value);
209 }
210
211 void push_back(value_type&& value)
212 {
213 if (_storage.size() >= max_capacity::value)
214 throw PacketArrayMaxCapacityException(_storage.size() + 1, max_capacity::value);
215
216 _storage.push_back(std::forward<value_type>(value));
217 }
218
219 template<typename... Args>
220 T& emplace_back(Args&&... args)
221 {
222 _storage.emplace_back(std::forward<Args>(args)...);
223 return _storage.back();
224 }
225
227 {
228 return _storage.erase(first, last);
229 }
230
231 void clear()
232 {
233 _storage.clear();
234 }
235
236 private:
239 };
240
241 template<typename Underlying = int64>
243 {
244 public:
245 Timestamp() = default;
246 Timestamp(time_t value) : _value(value) { }
247 Timestamp(SystemTimePoint const& systemTime) : _value(std::chrono::system_clock::to_time_t(systemTime)) { }
248
249 Timestamp& operator=(time_t value)
250 {
251 _value = value;
252 return *this;
253 }
254
256 {
257 _value = std::chrono::system_clock::to_time_t(systemTime);
258 return *this;
259 }
260
261 operator time_t() const
262 {
263 return _value;
264 }
265
266 Underlying AsUnderlyingType() const
267 {
268 return static_cast<Underlying>(_value);
269 }
270
271 friend ByteBuffer& operator<<(ByteBuffer& data, Timestamp timestamp)
272 {
273 data << static_cast<Underlying>(timestamp._value);
274 return data;
275 }
276
277 friend ByteBuffer& operator>>(ByteBuffer& data, Timestamp& timestamp)
278 {
279 timestamp._value = data.read<time_t, Underlying>();
280 return data;
281 }
282
283 private:
284 time_t _value = time_t(0);
285 };
286
287 template<typename ChronoDuration, typename Underlying = int64>
289 {
290 public:
291 Duration() = default;
292 Duration(ChronoDuration value) : _value(value) { }
293
294 Duration& operator=(ChronoDuration value)
295 {
296 _value = value;
297 return *this;
298 }
299
300 operator ChronoDuration() const
301 {
302 return _value;
303 }
304
305 friend ByteBuffer& operator<<(ByteBuffer& data, Duration duration)
306 {
307 data << static_cast<Underlying>(duration._value.count());
308 return data;
309 }
310
311 friend ByteBuffer& operator>>(ByteBuffer& data, Duration& duration)
312 {
313 duration._value = ChronoDuration(data.read<Underlying>());
314 return data;
315 }
316
317 private:
318 ChronoDuration _value = ChronoDuration::zero();
319 };
320}
321
322#endif // PacketUtilities_h__
std::chrono::system_clock::time_point SystemTimePoint
Definition: Duration.h:42
std::string ReadCString(bool requireValidUtf8=true)
Definition: ByteBuffer.cpp:63
typename storage_type::iterator iterator
short_alloc::short_alloc< T,(N *sizeof(T)+(alignof(std::max_align_t) - 1)) &~(alignof(std::max_align_t) - 1)> allocator_type
const_pointer data() const
iterator erase(const_iterator first, const_iterator last)
T & emplace_back(Args &&... args)
Array & operator=(Array &&other) noexcept=delete
std::vector< T, allocator_type > storage_type
typename storage_type::const_pointer const_pointer
typename storage_type::const_reference const_reference
void push_back(value_type const &value)
const_iterator end() const
typename storage_type::reference reference
typename storage_type::size_type size_type
Array & operator=(Array const &other)
typename storage_type::value_type value_type
const_reference operator[](size_type i) const
void push_back(value_type &&value)
Array(Array &&other) noexcept=delete
typename storage_type::const_iterator const_iterator
size_type size() const
typename storage_type::pointer pointer
std::integral_constant< std::size_t, N > max_capacity
typename allocator_type::arena_type arena_type
reference operator[](size_type i)
const_iterator begin() const
void resize(size_type newSize)
Array(Array const &other)
Duration & operator=(ChronoDuration value)
friend ByteBuffer & operator>>(ByteBuffer &data, Duration &duration)
Duration(ChronoDuration value)
friend ByteBuffer & operator<<(ByteBuffer &data, Duration duration)
IllegalHyperlinkException(std::string const &value)
InvalidHyperlinkException(std::string const &value)
InvalidStringValueException(std::string const &value)
std::string const & GetInvalidValue() const
InvalidUtf8ValueException(std::string const &value)
PacketArrayMaxCapacityException(std::size_t requestedSize, std::size_t sizeLimit)
char const * c_str() const
std::conditional_t<!Trinity::has_type< Strings::RawBytes, std::tuple< Validators... > >::value, std::tuple< Strings::ByteSize< MaxBytesWithoutNullTerminator >, Strings::Utf8, Validators... >, std::tuple< Strings::ByteSize< MaxBytesWithoutNullTerminator >, Validators... > > ValidatorList
static bool ValidateNth(std::string const &value, std::index_sequence< indexes... >)
String & operator=(std::string const &value)
std::size_t length() const
static bool Validate(std::string const &value)
String & operator=(std::string &&value)
friend ByteBuffer & operator>>(ByteBuffer &data, String &value)
std::string && Move()
Underlying AsUnderlyingType() const
Timestamp & operator=(time_t value)
friend ByteBuffer & operator<<(ByteBuffer &data, Timestamp timestamp)
Timestamp & operator=(SystemTimePoint const &systemTime)
friend ByteBuffer & operator>>(ByteBuffer &data, Timestamp &timestamp)
Timestamp(SystemTimePoint const &systemTime)
STL namespace.
static bool Validate(std::string const &value)
static bool Validate(std::string const &)
static bool Validate(std::string const &value)