TrinityCore
Loading...
Searching...
No Matches
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 TRINITYCORE_PACKET_UTILITIES_H
19#define TRINITYCORE_PACKET_UTILITIES_H
20
21#include "ByteBuffer.h"
22#include "Duration.h"
23#include "Types.h"
24#include <short_alloc/short_alloc.h>
25#include <string_view>
26#include <ctime>
27
28namespace WorldPackets
29{
31 {
32 public:
33 explicit InvalidStringValueException(char const* type, std::string_view value);
34
35 std::string const& GetInvalidValue() const { return _value; }
36
37 private:
38 std::string _value;
39 };
40
42 {
43 public:
44 explicit InvalidUtf8ValueException(std::string_view value);
45 };
46
48 {
49 public:
55
56 explicit InvalidHyperlinkException(std::string_view value, Reason reason);
57
58 Reason GetReason() const { return _reason; }
59
60 private:
61 static char const* GetReasonText(Reason reason);
62
64 };
65
66 namespace Strings
67 {
68 struct RawBytes { static void Validate(std::string_view /*value*/) { } };
69 struct ByteSize { static void Validate(std::string_view value, std::size_t maxSize); };
70 struct Utf8 { static void Validate(std::string_view value); };
71 struct Hyperlinks { static void Validate(std::string_view value); };
72 struct NoHyperlinks { static void Validate(std::string_view value); };
73 }
74
78 template <std::size_t MaxBytesWithoutNullTerminator, typename... Validators>
79 class String
80 {
81 public:
82 bool empty() const { return _storage.empty(); }
83 std::size_t length() const { return _storage.length(); }
84 char const* c_str() const { return _storage.c_str(); }
85
86 operator std::string_view() const { return _storage; }
87 operator std::string&() & { return _storage; }
88 operator std::string const&() const & { return _storage; }
89 operator std::string&&() && { return std::move(_storage); }
90
91 friend ByteBuffer& operator>>(ByteBuffer& data, String& value)
92 {
93 value = data.ReadCString(false);
94 return data;
95 }
96
97 String& operator=(std::string const& value)
98 {
99 Validate(value);
100 _storage = value;
101 return *this;
102 }
103
104 String& operator=(std::string&& value)
105 {
106 Validate(value);
107 _storage = std::move(value);
108 return *this;
109 }
110
111 String& operator=(std::string_view value)
112 {
113 Validate(value);
114 _storage = std::move(value);
115 return *this;
116 }
117
118 String& operator=(char const* value)
119 {
120 return *this = std::string_view(value);
121 }
122
123 void resize(std::size_t size)
124 {
125 _storage.resize(size);
126 }
127
128 private:
129 static void Validate(std::string_view value)
130 {
131 Strings::ByteSize::Validate(value, MaxBytesWithoutNullTerminator);
132
133 if constexpr (!Trinity::has_type_in_list_v<Strings::RawBytes, Validators...> && !Trinity::has_type_in_list_v<Strings::Utf8, Validators...>)
135
136 (Validators::Validate(value), ...);
137 }
138
139 std::string _storage;
140 };
141
143 {
144 public:
145 PacketArrayMaxCapacityException(std::size_t requestedSize, std::size_t sizeLimit);
146 };
147
148 [[noreturn]] void OnInvalidArraySize(std::size_t requestedSize, std::size_t sizeLimit);
149
150 template <typename T, std::size_t N, bool IsLarge>
152 {
153 using allocator_type = short_alloc::short_alloc<T, (N * sizeof(T) + (alignof(std::max_align_t) - 1)) & ~(alignof(std::max_align_t) - 1)>;
154 using resource_type = typename allocator_type::arena_type;
155 };
156
157 // don't store elements inline when size is large
158 template <typename T, std::size_t N>
159 struct ArrayAllocatorTraits<T, N, true>
160 {
161 using allocator_type = std::allocator<T>;
162 using resource_type = std::allocator<T>;
163 };
164
168 template<typename T, std::size_t N>
169 class Array
170 {
171 public:
172 using allocator_traits = ArrayAllocatorTraits<T, N, (sizeof(T) * N > 0x1000)>;
175
176 using storage_type = std::vector<T, allocator_type>;
177
178 using max_capacity = std::integral_constant<std::size_t, N>;
179
180 using value_type = typename storage_type::value_type;
181 using size_type = typename storage_type::size_type;
182 using pointer = typename storage_type::pointer;
183 using const_pointer = typename storage_type::const_pointer;
184 using reference = typename storage_type::reference;
185 using const_reference = typename storage_type::const_reference;
186 using iterator = typename storage_type::iterator;
187 using const_iterator = typename storage_type::const_iterator;
188
190
191 Array(Array const& other) : Array()
192 {
193 for (T const& element : other)
194 _storage.push_back(element);
195 }
196
197 Array(Array&& other) noexcept = delete;
198
199 Array& operator=(Array const& other)
200 {
201 if (this == &other)
202 return *this;
203
204 _storage.clear();
205 for (T const& element : other)
206 _storage.push_back(element);
207
208 return *this;
209 }
210
211 Array& operator=(Array&& other) noexcept = delete;
212
213 ~Array() = default;
214
215 iterator begin() { return _storage.begin(); }
216 const_iterator begin() const { return _storage.begin(); }
217
218 iterator end() { return _storage.end(); }
219 const_iterator end() const { return _storage.end(); }
220
221 pointer data() { return _storage.data(); }
222 const_pointer data() const { return _storage.data(); }
223
224 size_type size() const { return _storage.size(); }
225 bool empty() const { return _storage.empty(); }
226
229
230 void resize(size_type newSize)
231 {
232 if (newSize > max_capacity::value)
233 OnInvalidArraySize(newSize, max_capacity::value);
234
235 _storage.resize(newSize);
236 }
237
238 void push_back(value_type const& value)
239 {
240 if (_storage.size() >= max_capacity::value)
241 OnInvalidArraySize(_storage.size() + 1, max_capacity::value);
242
243 _storage.push_back(value);
244 }
245
246 void push_back(value_type&& value)
247 {
248 if (_storage.size() >= max_capacity::value)
249 OnInvalidArraySize(_storage.size() + 1, max_capacity::value);
250
251 _storage.push_back(std::forward<value_type>(value));
252 }
253
254 template<typename... Args>
255 T& emplace_back(Args&&... args)
256 {
257 _storage.emplace_back(std::forward<Args>(args)...);
258 return _storage.back();
259 }
260
262 {
263 return _storage.erase(first, last);
264 }
265
266 void clear()
267 {
268 _storage.clear();
269 }
270
271 private:
274 };
275
276 template<typename Underlying = int64>
278 {
279 public:
280 Timestamp() = default;
281 Timestamp(time_t value) : _value(value) { }
282 Timestamp(SystemTimePoint const& systemTime) : _value(std::chrono::system_clock::to_time_t(systemTime)) { }
283
284 Timestamp& operator=(time_t value)
285 {
286 _value = value;
287 return *this;
288 }
289
291 {
292 _value = std::chrono::system_clock::to_time_t(systemTime);
293 return *this;
294 }
295
296 operator time_t() const
297 {
298 return _value;
299 }
300
301 Underlying AsUnderlyingType() const
302 {
303 return static_cast<Underlying>(_value);
304 }
305
306 friend ByteBuffer& operator<<(ByteBuffer& data, Timestamp timestamp)
307 {
308 data << static_cast<Underlying>(timestamp._value);
309 return data;
310 }
311
312 friend ByteBuffer& operator>>(ByteBuffer& data, Timestamp& timestamp)
313 {
314 timestamp._value = static_cast<time_t>(data.read<Underlying>());
315 return data;
316 }
317
318 private:
319 time_t _value = time_t(0);
320 };
321
322 template<typename ChronoDuration, typename Underlying = int64>
324 {
325 public:
326 Duration() = default;
327 Duration(ChronoDuration value) : _value(value) { }
328
329 Duration& operator=(ChronoDuration value)
330 {
331 _value = value;
332 return *this;
333 }
334
335 operator ChronoDuration() const
336 {
337 return _value;
338 }
339
340 friend ByteBuffer& operator<<(ByteBuffer& data, Duration duration)
341 {
342 data << static_cast<Underlying>(duration._value.count());
343 return data;
344 }
345
346 friend ByteBuffer& operator>>(ByteBuffer& data, Duration& duration)
347 {
348 duration._value = ChronoDuration(data.read<Underlying>());
349 return data;
350 }
351
352 private:
353 ChronoDuration _value = ChronoDuration::zero();
354 };
355}
356
357#endif // TRINITYCORE_PACKET_UTILITIES_H
uint8_t uint8
Definition Define.h:156
std::chrono::system_clock::time_point SystemTimePoint
Definition Duration.h:41
std::string_view ReadCString(bool requireValidUtf8=true)
typename allocator_traits::allocator_type allocator_type
typename storage_type::iterator iterator
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
typename allocator_traits::resource_type allocator_resource_type
Array & operator=(Array const &other)
typename storage_type::value_type value_type
const_reference operator[](size_type i) const
allocator_resource_type _allocatorResource
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
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)
static char const * GetReasonText(Reason reason)
std::string const & GetInvalidValue() const
char const * c_str() const
void resize(std::size_t size)
String & operator=(std::string const &value)
String & operator=(std::string_view value)
std::size_t length() const
static void Validate(std::string_view value)
String & operator=(std::string &&value)
friend ByteBuffer & operator>>(ByteBuffer &data, String &value)
String & operator=(char const *value)
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)
constexpr bool has_type_in_list_v
Definition Types.h:67
void OnInvalidArraySize(std::size_t requestedSize, std::size_t sizeLimit)
STL namespace.
typename allocator_type::arena_type resource_type
short_alloc::short_alloc< T,(N *sizeof(T)+(alignof(std::max_align_t) - 1)) &~(alignof(std::max_align_t) - 1)> allocator_type
static void Validate(std::string_view value, std::size_t maxSize)
static void Validate(std::string_view)
static void Validate(std::string_view value)